Merge branch 'master' into upstream-merge-6762

This commit is contained in:
Novacat
2020-03-09 01:45:23 -04:00
committed by GitHub
199 changed files with 16129 additions and 12876 deletions
+60
View File
@@ -0,0 +1,60 @@
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
1. Definitions
"Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License.
"Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(g) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License.
"Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership.
"License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, Noncommercial, ShareAlike.
"Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License.
"Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast.
"Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work.
"You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
"Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images.
"Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium.
2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws.
3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:
to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections;
to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified.";
to Distribute and Publicly Perform the Work including as incorporated in Collections; and,
to Distribute and Publicly Perform Adaptations.
The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved, including but not limited to the rights described in Section 4(e).
4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:
You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(d), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(d), as requested.
You may Distribute or Publicly Perform an Adaptation only under: (i) the terms of this License; (ii) a later version of this License with the same License Elements as this License; (iii) a Creative Commons jurisdiction license (either this or a later license version) that contains the same License Elements as this License (e.g., Attribution-NonCommercial-ShareAlike 3.0 US) ("Applicable License"). You must include a copy of, or the URI, for Applicable License with every copy of each Adaptation You Distribute or Publicly Perform. You may not offer or impose any terms on the Adaptation that restrict the terms of the Applicable License or the ability of the recipient of the Adaptation to exercise the rights granted to that recipient under the terms of the Applicable License. You must keep intact all notices that refer to the Applicable License and to the disclaimer of warranties with every copy of the Work as included in the Adaptation You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Adaptation, You may not impose any effective technological measures on the Adaptation that restrict the ability of a recipient of the Adaptation from You to exercise the rights granted to that recipient under the terms of the Applicable License. This Section 4(b) applies to the Adaptation as incorporated in a Collection, but this does not require the Collection apart from the Adaptation itself to be made subject to the terms of the Applicable License.
You may not exercise any of the rights granted to You in Section 3 above in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. The exchange of the Work for other copyrighted works by means of digital file-sharing or otherwise shall not be considered to be intended for or directed toward commercial advantage or private monetary compensation, provided there is no payment of any monetary compensation in con-nection with the exchange of copyrighted works.
If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and, (iv) consistent with Section 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4(d) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties.
For the avoidance of doubt:
Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License;
Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License if Your exercise of such rights is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(c) and otherwise waives the right to collect royalties through any statutory or compulsory licensing scheme; and,
Voluntary License Schemes. The Licensor reserves the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License that is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(c).
Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise.
5. Representations, Warranties and Disclaimer
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING AND TO THE FULLEST EXTENT PERMITTED BY APPLICABLE LAW, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO THIS EXCLUSION MAY NOT APPLY TO YOU.
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. Termination
This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.
8. Miscellaneous
Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License.
If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.
The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law.
+8
View File
@@ -21,6 +21,14 @@ If you wish to develop and host this codebase in a closed source manner you may
See [here](https://www.gnu.org/licenses/why-affero-gpl.html) for more information.
Any files located in the
`vorestation/goon`,
`vorestation/icons/goonstation`, or
`vorestation/sound/goonstation`
directories, or any subdirectories of mentioned directories are licensed under the
Creative Commons 3.0 BY-NC-SA license
(https://creativecommons.org/licenses/by-nc-sa/3.0)
All assets including icons and sound are under a [CC BY-SA 3.0](http://creativecommons.org/licenses/by-sa/3.0/) license unless otherwise indicated.
### GETTING THE CODE
+3
View File
@@ -15,6 +15,9 @@
//#define ZASDBG // Uncomment to turn on super detailed ZAS debugging that probably won't even compile.
#define MULTIZAS // Uncomment to turn on Multi-Z ZAS Support!
// Comment/Uncomment this to turn off/on shuttle code debugging logs
#define DEBUG_SHUTTLES
// If we are doing the map test build, do not include the main maps, only the submaps.
#if MAP_TEST
#define USING_MAP_DATUM /datum/map
+3
View File
@@ -18,6 +18,9 @@
#define LAZYOR(L, I) if(!L) { L = list(); } L |= I;
// Adds I to L, initalizing L if necessary, if I is not already in L
#define LAZYDISTINCTADD(L, I) if(!L) { L = list(); } L |= I;
#define LAZYFIND(L, V) L ? L.Find(V) : 0
// Reads I from L safely - Works with both associative and traditional lists.
+1
View File
@@ -26,6 +26,7 @@
#define QDEL_IN(item, time) addtimer(CALLBACK(GLOBAL_PROC, .proc/qdel, item), time, TIMER_STOPPABLE)
#define QDEL_IN_CLIENT_TIME(item, time) addtimer(CALLBACK(GLOBAL_PROC, .proc/qdel, item), time, TIMER_STOPPABLE | TIMER_CLIENT_TIME)
#define QDEL_NULL(item) qdel(item); item = null
#define QDEL_NULL_LIST QDEL_LIST_NULL
#define QDEL_LIST_NULL(x) if(x) { for(var/y in x) { qdel(y) } ; x = null }
#define QDEL_LIST(L) if(L) { for(var/I in L) qdel(I); L.Cut(); }
#define QDEL_LIST_IN(L, time) addtimer(CALLBACK(GLOBAL_PROC, .proc/______qdel_list_wrapper, L), time, TIMER_STOPPABLE)
+5
View File
@@ -308,6 +308,11 @@ proc/listclearnulls(list/list)
else
L[key] = temp[key]
// Return a list of the values in an assoc list (including null)
/proc/list_values(var/list/L)
. = list()
for(var/e in L)
. += L[e]
//Mergesort: divides up the list into halves to begin the sort
/proc/sortKey(var/list/client/L, var/order = 1)
+117 -1
View File
@@ -38,4 +38,120 @@
var/pressure = environment ? environment.return_pressure() : 0
if(pressure < SOUND_MINIMUM_PRESSURE)
return TRUE
return FALSE
return FALSE
/*
Turf manipulation
*/
//Returns an assoc list that describes how turfs would be changed if the
//turfs in turfs_src were translated by shifting the src_origin to the dst_origin
/proc/get_turf_translation(turf/src_origin, turf/dst_origin, list/turfs_src)
var/list/turf_map = list()
for(var/turf/source in turfs_src)
var/x_pos = (source.x - src_origin.x)
var/y_pos = (source.y - src_origin.y)
var/z_pos = (source.z - src_origin.z)
var/turf/target = locate(dst_origin.x + x_pos, dst_origin.y + y_pos, dst_origin.z + z_pos)
if(!target)
error("Null turf in translation @ ([dst_origin.x + x_pos], [dst_origin.y + y_pos], [dst_origin.z + z_pos])")
turf_map[source] = target //if target is null, preserve that information in the turf map
return turf_map
/proc/translate_turfs(var/list/translation, var/area/base_area = null, var/turf/base_turf)
for(var/turf/source in translation)
var/turf/target = translation[source]
if(target)
if(base_area) ChangeArea(target, get_area(source))
var/leave_turf = base_turf ? base_turf : get_base_turf_by_area(base_area ? base_area : source)
translate_turf(source, target, leave_turf)
if(base_area) ChangeArea(source, base_area)
//change the old turfs (Currently done by translate_turf for us)
//for(var/turf/source in translation)
// source.ChangeTurf(base_turf ? base_turf : get_base_turf_by_area(source), 1, 1)
// Parmaters for stupid historical reasons are:
// T - Origin
// B - Destination
/proc/translate_turf(var/turf/T, var/turf/B, var/turftoleave = null)
//You can stay, though.
if(istype(T,/turf/space))
error("Tried to translate a space turf: src=[log_info_line(T)] dst=[log_info_line(B)]")
return FALSE // TODO - Is this really okay to do nothing?
var/turf/X //New Destination Turf
//Are we doing shuttlework? Just to save another type check later.
var/shuttlework = 0
//Shuttle turfs handle their own fancy moving.
if(istype(T,/turf/simulated/shuttle))
shuttlework = 1
var/turf/simulated/shuttle/SS = T
if(!SS.landed_holder) SS.landed_holder = new(turf = SS)
X = SS.landed_holder.land_on(B)
//Generic non-shuttle turf move.
else
var/old_dir1 = T.dir
var/old_icon_state1 = T.icon_state
var/old_icon1 = T.icon
var/old_underlays = T.underlays.Copy()
var/old_decals = T.decals ? T.decals.Copy() : null
X = B.ChangeTurf(T.type)
X.set_dir(old_dir1)
X.icon_state = old_icon_state1
X.icon = old_icon1
X.copy_overlays(T, TRUE)
X.underlays = old_underlays
X.decals = old_decals
//Move the air from source to dest
var/turf/simulated/ST = T
if(istype(ST) && ST.zone)
var/turf/simulated/SX = X
if(!SX.air)
SX.make_air()
SX.air.copy_from(ST.zone.air)
ST.zone.remove(ST)
var/z_level_change = FALSE
if(T.z != X.z)
z_level_change = TRUE
//Move the objects. Not forceMove because the object isn't "moving" really, it's supposed to be on the "same" turf.
for(var/obj/O in T)
if(O.simulated)
O.loc = X
O.update_light()
if(z_level_change) // The objects still need to know if their z-level changed.
O.onTransitZ(T.z, X.z)
//Move the mobs unless it's an AI eye or other eye type.
for(var/mob/M in T)
if(isEye(M)) continue // If we need to check for more mobs, I'll add a variable
M.loc = X
if(z_level_change) // Same goes for mobs.
M.onTransitZ(T.z, X.z)
if(istype(M, /mob/living))
var/mob/living/LM = M
LM.check_shadow() // Need to check their Z-shadow, which is normally done in forceMove().
if(shuttlework)
var/turf/simulated/shuttle/SS = T
SS.landed_holder.leave_turf(turftoleave)
else if(turftoleave)
T.ChangeTurf(turftoleave)
else
T.ChangeTurf(get_base_turf_by_area(T))
return TRUE
+2
View File
@@ -25,6 +25,8 @@
#define qdel_null(x) if(x) { qdel(x) ; x = null }
#define sequential_id(key) uniqueness_repository.Generate(/datum/uniqueness_generator/id_sequential, key)
#define random_id(key,min_id,max_id) uniqueness_repository.Generate(/datum/uniqueness_generator/id_random, key, min_id, max_id)
#define ARGS_DEBUG log_debug("[__FILE__] - [__LINE__]") ; for(var/arg in args) { log_debug("\t[log_info_line(arg)]") }
+3 -6
View File
@@ -134,12 +134,6 @@
// A is a turf or is on a turf, or in something on a turf (pen in a box); but not something in something on a turf (pen in a box in a backpack)
sdepth = A.storage_depth_turf()
if(isturf(A) || isturf(A.loc) || (sdepth != -1 && sdepth <= 1))
//VOREStation Edit begin: SHADEKIN
var/mob/SK = src
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
if(A.Adjacent(src) || (W && W.attack_can_reach(src, A, W.reach)) ) // see adjacent.dm
if(W)
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
@@ -188,6 +182,9 @@
/mob/living/UnarmedAttack(var/atom/A, var/proximity_flag)
if(is_incorporeal())
return 0
if(!ticker)
to_chat(src, "You cannot attack people before the game has started.")
return 0
+86 -91
View File
@@ -1,8 +1,5 @@
//Config stuff
#define SUPPLY_DOCKZ 2 //Z-level of the Dock.
#define SUPPLY_STATIONZ 1 //Z-level of the Station.
#define SUPPLY_STATION_AREATYPE "/area/supply/station" //Type of the supply shuttle area for station
#define SUPPLY_DOCK_AREATYPE "/area/supply/dock" //Type of the supply shuttle area for dock
// TODO - Refactor to use the Supply Subsystem (SSsupply)
//Supply packs are in /code/datums/supplypacks
//Computers are in /code/game/machinery/computer/supply.dm
@@ -43,7 +40,7 @@ var/datum/controller/supply/supply_controller = new()
var/list/adm_export_history = list() // Complete history of all crates sent back on the shuttle, for admin use
//shuttle movement
var/movetime = 1200
var/datum/shuttle/ferry/supply/shuttle
var/datum/shuttle/autodock/ferry/supply/shuttle
var/list/material_points_conversion = list( // Any materials not named in this list are worth 0 points
"phoron" = 5,
"platinum" = 5
@@ -90,83 +87,98 @@ var/datum/controller/supply/supply_controller = new()
//Selling
/datum/controller/supply/proc/sell()
var/area/area_shuttle = shuttle.get_location_area()
if(!area_shuttle)
return
// Loop over each area in the supply shuttle
for(var/area/subarea in shuttle.shuttle_area)
callHook("sell_shuttle", list(subarea));
for(var/atom/movable/MA in subarea)
if(MA.anchored)
continue
callHook("sell_shuttle", list(area_shuttle));
var/datum/exported_crate/EC = new /datum/exported_crate()
EC.name = "\proper[MA.name]"
EC.value = 0
EC.contents = list()
var/base_value = 0
for(var/atom/movable/MA in area_shuttle)
if(MA.anchored)
continue
// Must be in a crate!
if(istype(MA,/obj/structure/closet/crate))
var/obj/structure/closet/crate/CR = MA
callHook("sell_crate", list(CR, subarea))
var/datum/exported_crate/EC = new /datum/exported_crate()
EC.name = "\proper[MA.name]"
EC.value = 0
EC.contents = list()
var/base_value = 0
points += CR.points_per_crate
if(CR.points_per_crate)
base_value = CR.points_per_crate
var/find_slip = 1
// Must be in a crate!
if(istype(MA,/obj/structure/closet/crate))
var/obj/structure/closet/crate/CR = MA
callHook("sell_crate", list(CR, area_shuttle))
for(var/atom/A in CR)
EC.contents[++EC.contents.len] = list(
"object" = "\proper[A.name]",
"value" = 0,
"quantity" = 1
)
points += CR.points_per_crate
if(CR.points_per_crate)
base_value = CR.points_per_crate
var/find_slip = 1
// Sell manifests
if(find_slip && istype(A,/obj/item/weapon/paper/manifest))
var/obj/item/weapon/paper/manifest/slip = A
if(!slip.is_copy && slip.stamped && slip.stamped.len) //yes, the clown stamp will work. clown is the highest authority on the station, it makes sense
points += points_per_slip
EC.contents[EC.contents.len]["value"] = points_per_slip
find_slip = 0
continue
for(var/atom/A in CR)
EC.contents[++EC.contents.len] = list(
"object" = "\proper[A.name]",
"value" = 0,
"quantity" = 1
// Sell phoron and platinum
if(istype(A, /obj/item/stack))
var/obj/item/stack/P = A
if(material_points_conversion[P.get_material_name()])
EC.contents[EC.contents.len]["value"] = P.get_amount() * material_points_conversion[P.get_material_name()]
EC.contents[EC.contents.len]["quantity"] = P.get_amount()
EC.value += EC.contents[EC.contents.len]["value"]
//Sell spacebucks
if(istype(A, /obj/item/weapon/spacecash))
var/obj/item/weapon/spacecash/cashmoney = A
EC.contents[EC.contents.len]["value"] = cashmoney.worth * points_per_money
EC.contents[EC.contents.len]["quantity"] = cashmoney.worth
EC.value += EC.contents[EC.contents.len]["value"]
// Make a log of it, but it wasn't shipped properly, and so isn't worth anything
else
EC.contents = list(
"error" = "Error: Product was improperly packaged. Payment rendered null under terms of agreement."
)
// Sell manifests
if(find_slip && istype(A,/obj/item/weapon/paper/manifest))
var/obj/item/weapon/paper/manifest/slip = A
if(!slip.is_copy && slip.stamped && slip.stamped.len) //yes, the clown stamp will work. clown is the highest authority on the station, it makes sense
points += points_per_slip
EC.contents[EC.contents.len]["value"] = points_per_slip
find_slip = 0
exported_crates += EC
points += EC.value
EC.value += base_value
// Duplicate the receipt for the admin-side log
var/datum/exported_crate/adm = new()
adm.name = EC.name
adm.value = EC.value
adm.contents = deepCopyList(EC.contents)
adm_export_history += adm
qdel(MA)
/datum/controller/supply/proc/get_clear_turfs()
var/list/clear_turfs = list()
for(var/area/subarea in shuttle.shuttle_area)
for(var/turf/T in subarea)
if(T.density)
continue
var/occupied = 0
for(var/atom/A in T.contents)
if(!A.simulated)
continue
occupied = 1
break
if(!occupied)
clear_turfs += T
// Sell phoron and platinum
if(istype(A, /obj/item/stack))
var/obj/item/stack/P = A
if(material_points_conversion[P.get_material_name()])
EC.contents[EC.contents.len]["value"] = P.get_amount() * material_points_conversion[P.get_material_name()]
EC.contents[EC.contents.len]["quantity"] = P.get_amount()
EC.value += EC.contents[EC.contents.len]["value"]
//Sell spacebucks
if(istype(A, /obj/item/weapon/spacecash))
var/obj/item/weapon/spacecash/cashmoney = A
EC.contents[EC.contents.len]["value"] = cashmoney.worth * points_per_money
EC.contents[EC.contents.len]["quantity"] = cashmoney.worth
EC.value += EC.contents[EC.contents.len]["value"]
// Make a log of it, but it wasn't shipped properly, and so isn't worth anything
else
EC.contents = list(
"error" = "Error: Product was improperly packaged. Payment rendered null under terms of agreement."
)
exported_crates += EC
points += EC.value
EC.value += base_value
// Duplicate the receipt for the admin-side log
var/datum/exported_crate/adm = new()
adm.name = EC.name
adm.value = EC.value
adm.contents = deepCopyList(EC.contents)
adm_export_history += adm
qdel(MA)
return clear_turfs
//Buying
/datum/controller/supply/proc/buy()
@@ -177,26 +189,9 @@ var/datum/controller/supply/supply_controller = new()
if(!shoppinglist.len)
return
var/orderedamount = shoppinglist.len
var/area/area_shuttle = shuttle.get_location_area()
if(!area_shuttle)
return
var/list/clear_turfs = list()
for(var/turf/T in area_shuttle)
if(T.density)
continue
var/contcount
for(var/atom/A in T.contents)
if(!A.simulated)
continue
contcount++
if(contcount)
continue
clear_turfs += T
var/list/clear_turfs = get_clear_turfs()
for(var/datum/supply_order/SO in shoppinglist)
if(!clear_turfs.len)
+4
View File
@@ -31,6 +31,7 @@ var/list/gamemode_cache = list()
var/allow_admin_jump = 1 // allows admin jumping
var/allow_admin_spawning = 1 // allows admin item spawning
var/allow_admin_rev = 1 // allows admin revives
var/pregame_time = 180 // pregame time in seconds
var/vote_delay = 6000 // minimum time between voting sessions (deciseconds, 10 minute default)
var/vote_period = 600 // length of voting period (deciseconds, default 1 minute)
var/vote_autotransfer_initial = 108000 // Length of time before the first autotransfer vote is called
@@ -420,6 +421,9 @@ var/list/gamemode_cache = list()
if ("default_no_vote")
config.vote_no_default = 1
if ("pregame_time")
config.pregame_time = text2num(value)
if ("vote_delay")
config.vote_delay = text2num(value)
@@ -5,7 +5,7 @@
var/global/datum/emergency_shuttle_controller/emergency_shuttle
/datum/emergency_shuttle_controller
var/datum/shuttle/ferry/emergency/shuttle
var/datum/shuttle/autodock/ferry/emergency/shuttle // Set in shuttle_emergency.dm TODO - is it really?
var/list/escape_pods
var/launch_time //the time at which the shuttle will be launched
@@ -36,8 +36,8 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
if (!shuttle.location) //leaving from the station
//launch the pods!
for (var/EP in escape_pods)
var/datum/shuttle/ferry/escape_pod/pod
if(istype(escape_pods[EP], /datum/shuttle/ferry/escape_pod))
var/datum/shuttle/autodock/ferry/escape_pod/pod
if(istype(escape_pods[EP], /datum/shuttle/autodock/ferry/escape_pod))
pod = escape_pods[EP]
else
continue
@@ -63,8 +63,8 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
//arm the escape pods
if (evac)
for (var/EP in escape_pods)
var/datum/shuttle/ferry/escape_pod/pod
if(istype(escape_pods[EP], /datum/shuttle/ferry/escape_pod))
var/datum/shuttle/autodock/ferry/escape_pod/pod
if(istype(escape_pods[EP], /datum/shuttle/autodock/ferry/escape_pod))
pod = escape_pods[EP]
else
continue
@@ -215,11 +215,11 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
//returns 1 if the shuttle is currently in transit (or just leaving) to the station
/datum/emergency_shuttle_controller/proc/going_to_station()
return (!shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
return shuttle && (!shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
//returns 1 if the shuttle is currently in transit (or just leaving) to centcom
/datum/emergency_shuttle_controller/proc/going_to_centcom()
return (shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
return shuttle && (shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
/datum/emergency_shuttle_controller/proc/get_status_panel_eta()
+1 -1
View File
@@ -25,7 +25,7 @@ SUBSYSTEM_DEF(ai)
// var/mob/living/L = currentrun[currentrun.len]
var/datum/ai_holder/A = currentrun[currentrun.len]
--currentrun.len
if(!A || QDELETED(A)) // Doesn't exist or won't exist soon.
if(!A || QDELETED(A) || A.busy) // Doesn't exist or won't exist soon or not doing it this tick
continue
if(times_fired % 4 == 0 && A.holder.stat != DEAD)
A.handle_strategicals()
+51 -35
View File
@@ -1,42 +1,58 @@
SUBSYSTEM_DEF(inactivity)
name = "AFK Kick"
wait = 600
flags = SS_BACKGROUND | SS_NO_TICK_CHECK
name = "Inactivity"
wait = 1 MINUTE
flags = SS_NO_INIT | SS_BACKGROUND
var/tmp/list/client_list
var/number_kicked = 0
/datum/controller/subsystem/inactivity/fire()
if(config.kick_inactive)
for(var/i in GLOB.clients)
var/client/C = i
if(C.is_afk(config.kick_inactive MINUTES) && !C.holder) // VOREStation Edit - Allow admins to idle
to_chat(C,"<span class='warning'>You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected.</span>")
var/information
/datum/controller/subsystem/inactivity/fire(resumed = FALSE)
if (!config.kick_inactive)
can_fire = FALSE
return
if (!resumed)
client_list = GLOB.clients.Copy()
if(C.mob)
if(ishuman(C.mob))
var/job
var/mob/living/carbon/human/H = C.mob
var/datum/data/record/R = find_general_record("name", H.real_name)
if(R)
job = R.fields["real_rank"]
if(!job && H.mind)
job = H.mind.assigned_role
if(!job && H.job)
job = H.job
if(job)
information = " while [job]."
while(client_list.len)
var/client/C = client_list[client_list.len]
client_list.len--
if(!C.holder && C.is_afk(config.kick_inactive MINUTES) && !isobserver(C.mob))
to_chat(C, "<span class='warning'>You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected.</span>")
else if(issilicon(C.mob))
information = " while a silicon."
if(isAI(C.mob))
var/mob/living/silicon/ai/A = C.mob
empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(A.loc)
global_announcer.autosay("[A] has been moved to intelligence storage.", "Artificial Intelligence Oversight")
A.clear_client()
information = " while an AI."
var/information
if(C.mob)
if(ishuman(C.mob))
var/job
var/mob/living/carbon/human/H = C.mob
var/datum/data/record/R = find_general_record("name", H.real_name)
if(R)
job = R.fields["real_rank"]
if(!job && H.mind)
job = H.mind.assigned_role
if(!job && H.job)
job = H.job
if(job)
information = " while [job]."
var/adminlinks
adminlinks = " (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[C.mob.x];Y=[C.mob.y];Z=[C.mob.z]'>JMP</a>|<A HREF='?_src_=holder;cryoplayer=\ref[C.mob]'>CRYO</a>)"
else if(issilicon(C.mob))
information = " while a silicon."
if(isAI(C.mob))
var/mob/living/silicon/ai/A = C.mob
empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(A.loc)
global_announcer.autosay("[A] has been moved to intelligence storage.", "Artificial Intelligence Oversight")
A.clear_client()
information = " while an AI."
log_and_message_admins("being kicked for AFK[information][adminlinks]", C.mob)
var/adminlinks
adminlinks = " (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[C.mob.x];Y=[C.mob.y];Z=[C.mob.z]'>JMP</a>|<A HREF='?_src_=holder;cryoplayer=\ref[C.mob]'>CRYO</a>)"
qdel(C)
log_and_message_admins("being kicked for AFK[information][adminlinks]", C.mob)
qdel(C)
number_kicked++
if (MC_TICK_CHECK)
return
/datum/controller/subsystem/inactivity/stat_entry()
..("Kicked: [number_kicked]")
+152 -53
View File
@@ -1,6 +1,8 @@
//
// SSshuttles subsystem - Handles initialization and processing of shuttles.
//
// Also handles initialization and processing of overmap sectors.
//
// This global variable exists for legacy support so we don't have to rename every shuttle_controller to SSshuttles yet.
var/global/datum/controller/subsystem/shuttles/shuttle_controller
@@ -13,71 +15,168 @@ SUBSYSTEM_DEF(shuttles)
flags = SS_KEEP_TIMING|SS_NO_TICK_CHECK
runlevels = RUNLEVEL_GAME|RUNLEVEL_POSTGAME
var/list/shuttles = list() // Maps shuttle tags to shuttle datums, so that they can be looked up.
var/list/process_shuttles = list() // Simple list of shuttles, for processing
var/list/current_run = list() // Shuttles remaining to process this fire() tick
var/list/docks_init_callbacks // List of callbacks to run when we finish setting up shuttle docks.
var/docks_initialized = FALSE
// TODO OVERMAP - These two are unused for now
var/overmap_halted = FALSE // Whether ships can move on the overmap; used for adminbus.
var/list/ships = list() // List of all ships.
var/list/shuttles = list() // Maps shuttle tags to shuttle datums, so that they can be looked up.
var/list/process_shuttles = list() // Simple list of shuttles, for processing
var/list/registered_shuttle_landmarks = list() // Maps shuttle landmark tags to instances
var/last_landmark_registration_time // world.time of most recent addition to registered_shuttle_landmarks
var/list/shuttle_logs = list() // (Not Implemented) Keeps records of shuttle movement, format is list(datum/shuttle = datum/shuttle_log)
var/list/shuttle_areas = list() // All the areas of all shuttles.
var/list/docking_registry = list() // Docking controller tag -> docking controller program, mostly for init purposes.
var/list/landmarks_awaiting_sector = list() // Stores automatic landmarks that are waiting for a sector to finish loading.
var/list/landmarks_still_needed = list() // Stores landmark_tags that need to be assigned to the sector (landmark_tag = sector) when registered.
var/list/shuttles_to_initialize // A queue for shuttles to initialize at the appropriate time.
var/list/sectors_to_initialize // Used to find all sector objects at the appropriate time.
var/block_init_queue = TRUE // Block initialization of new shuttles/sectors
var/tmp/list/current_run // Shuttles remaining to process this fire() tick
/datum/controller/subsystem/shuttles/PreInit()
global.shuttle_controller = src // TODO - Remove this! Change everything to point at SSshuttles intead
/datum/controller/subsystem/shuttles/Initialize(timeofday)
global.shuttle_controller = src
setup_shuttle_docks()
for(var/I in docks_init_callbacks)
var/datum/callback/cb = I
cb.InvokeAsync()
LAZYCLEARLIST(docks_init_callbacks)
docks_init_callbacks = null
last_landmark_registration_time = world.time
// Find all declared shuttle datums and initailize them. (Okay, queue them for initialization a few lines further down)
for(var/shuttle_type in subtypesof(/datum/shuttle)) // This accounts for most shuttles, though away maps can queue up more.
var/datum/shuttle/shuttle = shuttle_type
if(initial(shuttle.category) == shuttle_type)
continue // Its an "abstract class" datum, not for a real shuttle.
if(!initial(shuttle.defer_initialisation)) // Skip if it asks not to be initialized at startup.
LAZYDISTINCTADD(shuttles_to_initialize, shuttle_type)
block_init_queue = FALSE
process_init_queues()
return ..()
/datum/controller/subsystem/shuttles/fire(resumed = 0)
do_process_shuttles(resumed)
/datum/controller/subsystem/shuttles/stat_entry()
var/msg = list()
msg += "AS:[shuttles.len]|"
msg += "PS:[process_shuttles.len]|"
..(jointext(msg, null))
/datum/controller/subsystem/shuttles/proc/do_process_shuttles(resumed = 0)
if (!resumed)
src.current_run = process_shuttles.Copy()
var/list/current_run = src.current_run // Cache for sanic speed
while(current_run.len)
var/datum/shuttle/S = current_run[current_run.len]
current_run.len--
if(istype(S) && !QDELETED(S))
if(istype(S, /datum/shuttle/ferry)) // Ferry shuttles get special treatment
var/datum/shuttle/ferry/F = S
if(F.process_state || F.always_process)
F.process()
else
S.process()
else
var/list/working_shuttles = src.current_run // Cache for sanic speed
while(working_shuttles.len)
var/datum/shuttle/S = working_shuttles[working_shuttles.len]
working_shuttles.len--
if(!istype(S) || QDELETED(S))
error("Bad entry in SSshuttles.process_shuttles - [log_info_line(S)] ")
process_shuttles -= S
continue
// NOTE - In old system, /datum/shuttle/ferry was processed only if (F.process_state || F.always_process)
if(S.process_state && (S.process(wait, times_fired, src) == PROCESS_KILL))
process_shuttles -= S
if(MC_TICK_CHECK)
return
// This should be called after all the machines and radio frequencies have been properly initialized
/datum/controller/subsystem/shuttles/proc/setup_shuttle_docks()
// Find all declared shuttle datums and initailize them.
for(var/shuttle_type in subtypesof(/datum/shuttle))
var/datum/shuttle/shuttle = shuttle_type
if(initial(shuttle.category) == shuttle_type)
continue
/datum/controller/subsystem/shuttles/proc/process_init_queues()
if(block_init_queue)
return
initialize_shuttles()
initialize_sectors()
// Initializes all shuttles in shuttles_to_initialize
/datum/controller/subsystem/shuttles/proc/initialize_shuttles()
var/list/shuttles_made = list()
for(var/shuttle_type in shuttles_to_initialize)
var/shuttle = initialize_shuttle(shuttle_type)
if(shuttle)
shuttles_made += shuttle
hook_up_motherships(shuttles_made)
shuttles_to_initialize = null
/datum/controller/subsystem/shuttles/proc/initialize_sectors()
for(var/sector in sectors_to_initialize)
initialize_sector(sector)
sectors_to_initialize = null
/datum/controller/subsystem/shuttles/proc/register_landmark(shuttle_landmark_tag, obj/effect/shuttle_landmark/shuttle_landmark)
if (registered_shuttle_landmarks[shuttle_landmark_tag])
CRASH("Attempted to register shuttle landmark with tag [shuttle_landmark_tag], but it is already registered!")
if (istype(shuttle_landmark))
registered_shuttle_landmarks[shuttle_landmark_tag] = shuttle_landmark
last_landmark_registration_time = world.time
// TODO - Uncomment once overmap sectors are ported
//var/obj/effect/overmap/visitable/O = landmarks_still_needed[shuttle_landmark_tag]
//if(O) //These need to be added to sectors, which we handle.
// try_add_landmark_tag(shuttle_landmark_tag, O)
// landmarks_still_needed -= shuttle_landmark_tag
//else if(istype(shuttle_landmark, /obj/effect/shuttle_landmark/automatic)) //These find their sector automatically
// O = map_sectors["[shuttle_landmark.z]"]
// O ? O.add_landmark(shuttle_landmark, shuttle_landmark.shuttle_restricted) : (landmarks_awaiting_sector += shuttle_landmark)
/datum/controller/subsystem/shuttles/proc/get_landmark(var/shuttle_landmark_tag)
return registered_shuttle_landmarks[shuttle_landmark_tag]
//Checks if the given sector's landmarks have initialized; if so, registers them with the sector, if not, marks them for assignment after they come in.
//Also adds automatic landmarks that were waiting on their sector to spawn.
/datum/controller/subsystem/shuttles/proc/initialize_sector(obj/effect/overmap/visitable/given_sector)
return // TODO - Uncomment once overmap sectors are ported
// given_sector.populate_sector_objects() // This is a late init operation that sets up the sector's map_z and does non-overmap-related init tasks.
// for(var/landmark_tag in given_sector.initial_generic_waypoints)
// if(!try_add_landmark_tag(landmark_tag, given_sector))
// landmarks_still_needed[landmark_tag] = given_sector // Landmark isn't registered yet, queue it to be added once it is.
// for(var/shuttle_name in given_sector.initial_restricted_waypoints)
// for(var/landmark_tag in given_sector.initial_restricted_waypoints[shuttle_name])
// if(!try_add_landmark_tag(landmark_tag, given_sector))
// landmarks_still_needed[landmark_tag] = given_sector // Landmark isn't registered yet, queue it to be added once it is.
// var/landmarks_to_check = landmarks_awaiting_sector.Copy()
// for(var/thing in landmarks_to_check)
// var/obj/effect/shuttle_landmark/automatic/landmark = thing
// if(landmark.z in given_sector.map_z)
// given_sector.add_landmark(landmark, landmark.shuttle_restricted)
// landmarks_awaiting_sector -= landmark
// TODO - Uncomment once overmap sectors are ported
//// Attempts to add a landmark instance with a sector (returns false if landmark isn't registered yet)
///datum/controller/subsystem/shuttles/proc/try_add_landmark_tag(landmark_tag, obj/effect/overmap/visitable/given_sector)
// var/obj/effect/shuttle_landmark/landmark = get_landmark(landmark_tag)
// if(!landmark)
// return
// if(landmark.landmark_tag in given_sector.initial_generic_waypoints)
// given_sector.add_landmark(landmark)
// . = 1
// for(var/shuttle_name in given_sector.initial_restricted_waypoints)
// if(landmark.landmark_tag in given_sector.initial_restricted_waypoints[shuttle_name])
// given_sector.add_landmark(landmark, shuttle_name)
// . = 1
/datum/controller/subsystem/shuttles/proc/initialize_shuttle(var/shuttle_type)
var/datum/shuttle/shuttle = shuttle_type
if(initial(shuttle.category) != shuttle_type) // Skip if its an "abstract class" datum
shuttle = new shuttle()
shuttle.init_docking_controllers()
shuttle.dock() //makes all shuttles docked to something at round start go into the docked state
CHECK_TICK
shuttle_areas |= shuttle.shuttle_area
log_debug("Initialized shuttle [shuttle] ([shuttle.type])")
return shuttle
// Historical note: No need to call shuttle.init_docking_controllers(), controllers register themselves
// and shuttles fetch refs in New(). Shuttles also dock() themselves in new if they want.
for(var/obj/machinery/embedded_controller/C in machines)
if(istype(C.program, /datum/computer/file/embedded_program/docking))
C.program.tag = null //clear the tags, 'cause we don't need 'em anymore
docks_initialized = TRUE
// TODO - Leshana to hook up more of this when overmap is ported.
/datum/controller/subsystem/shuttles/proc/hook_up_motherships(shuttles_list)
for(var/datum/shuttle/S in shuttles_list)
if(S.mothershuttle && !S.motherdock)
var/datum/shuttle/mothership = shuttles[S.mothershuttle]
if(mothership)
S.motherdock = S.current_location.landmark_tag
mothership.shuttle_area |= S.shuttle_area
else
error("Shuttle [S] was unable to find mothership [mothership]!")
// Register a callback that will be invoked once the shuttles have been initialized
/datum/controller/subsystem/shuttles/proc/OnDocksInitialized(datum/callback/cb)
if(!docks_initialized)
LAZYADD(docks_init_callbacks, cb)
else
cb.InvokeAsync()
// Admin command to halt/resume overmap
// /datum/controller/subsystem/shuttles/proc/toggle_overmap(new_setting)
// if(overmap_halted == new_setting)
// return
// overmap_halted = !overmap_halted
// for(var/ship in ships)
// var/obj/effect/overmap/visitable/ship/ship_effect = ship
// overmap_halted ? ship_effect.halt() : ship_effect.unhalt()
/datum/controller/subsystem/shuttles/stat_entry()
..("Shuttles:[process_shuttles.len]/[shuttles.len], Ships:[ships.len], L:[registered_shuttle_landmarks.len][overmap_halted ? ", HALT" : ""]")
+4 -12
View File
@@ -138,12 +138,8 @@
return
/obj/effect/ebeam/deadly/Crossed(atom/A)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = A
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
if(A.is_incorporeal())
return
..()
A.ex_act(1)
@@ -163,12 +159,8 @@
on_contact(A)
/obj/effect/ebeam/reactive/Crossed(atom/A)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = A
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
if(A.is_incorporeal())
return
..()
on_contact(A)
+22
View File
@@ -0,0 +1,22 @@
// Observer Pattern Implementation: Shuttle Added
// Registration type: /datum/shuttle (register for the global event only)
//
// Raised when: After a shuttle is initialized.
//
// Arguments that the called proc should expect:
// /datum/shuttle/shuttle: the new shuttle
GLOBAL_DATUM_INIT(shuttle_added, /decl/observ/shuttle_added, new)
/decl/observ/shuttle_added
name = "Shuttle Added"
expected_type = /datum/shuttle
/*****************************
* Shuttle Added Handling *
*****************************/
/datum/controller/subsystem/shuttles/initialize_shuttle()
. = ..()
if(.)
GLOB.shuttle_added.raise_event(.)
+38
View File
@@ -0,0 +1,38 @@
// Observer Pattern Implementation: Shuttle Moved
// Registration type: /datum/shuttle/autodock
//
// Raised when: A shuttle has moved to a new landmark.
//
// Arguments that the called proc should expect:
// /datum/shuttle/shuttle: the shuttle moving
// /obj/effect/shuttle_landmark/old_location: the old location's shuttle landmark
// /obj/effect/shuttle_landmark/new_location: the new location's shuttle landmark
// Observer Pattern Implementation: Shuttle Pre Move
// Registration type: /datum/shuttle/autodock
//
// Raised when: A shuttle is about to move to a new landmark.
//
// Arguments that the called proc should expect:
// /datum/shuttle/shuttle: the shuttle moving
// /obj/effect/shuttle_landmark/old_location: the old location's shuttle landmark
// /obj/effect/shuttle_landmark/new_location: the new location's shuttle landmark
GLOBAL_DATUM_INIT(shuttle_moved_event, /decl/observ/shuttle_moved, new)
/decl/observ/shuttle_moved
name = "Shuttle Moved"
expected_type = /datum/shuttle
GLOBAL_DATUM_INIT(shuttle_pre_move_event, /decl/observ/shuttle_pre_move, new)
/decl/observ/shuttle_pre_move
name = "Shuttle Pre Move"
expected_type = /datum/shuttle
/*****************
* Shuttle Moved/Pre Move Handling *
*****************/
// Located in modules/shuttle/shuttle.dm
// Proc: /datum/shuttle/proc/attempt_move()
+3 -159
View File
@@ -62,8 +62,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
////////////
//SHUTTLES//
////////////
//shuttle areas must contain at least two areas in a subgroup if you want to move a shuttle from one
//place to another. Look at escape shuttle for example.
//Shuttles only need starting area, movement is handled by landmarks
//All shuttles should now be under shuttle since we have smooth-wall code.
/area/shuttle
@@ -76,160 +75,55 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "\improper Arrival Shuttle"
ambience = AMBIENCE_ARRIVALS
/area/shuttle/arrival/pre_game
/area/shuttle/supply
name = "\improper Supply Shuttle"
icon_state = "shuttle2"
/area/shuttle/arrival/station
icon_state = "shuttle"
dynamic_lighting = 0
ambience = AMBIENCE_ARRIVALS
/area/shuttle/escape
name = "\improper Emergency Shuttle"
music = "music/escape.ogg"
/area/shuttle/escape/station
name = "\improper Emergency Shuttle Station"
icon_state = "shuttle2"
dynamic_lighting = 0
/area/shuttle/escape/centcom
name = "\improper Emergency Shuttle CentCom"
icon_state = "shuttle"
/area/shuttle/escape/transit // the area to pass through for 3 minute transit
name = "\improper Emergency Shuttle Transit"
icon_state = "shuttle"
/area/shuttle/escape_pod1
name = "\improper Escape Pod One"
music = "music/escape.ogg"
/area/shuttle/escape_pod1/station
icon_state = "shuttle2"
/area/shuttle/escape_pod1/centcom
icon_state = "shuttle"
/area/shuttle/escape_pod1/transit
icon_state = "shuttle"
/area/shuttle/escape_pod2
name = "\improper Escape Pod Two"
music = "music/escape.ogg"
/area/shuttle/escape_pod2/station
icon_state = "shuttle2"
/area/shuttle/escape_pod2/centcom
icon_state = "shuttle"
/area/shuttle/escape_pod2/transit
icon_state = "shuttle"
/area/shuttle/escape_pod3
name = "\improper Escape Pod Three"
music = "music/escape.ogg"
/area/shuttle/escape_pod3/station
icon_state = "shuttle2"
/area/shuttle/escape_pod3/centcom
icon_state = "shuttle"
/area/shuttle/escape_pod3/transit
icon_state = "shuttle"
/area/shuttle/escape_pod4
name = "\improper Escape Pod Four"
music = "music/escape.ogg"
/area/shuttle/escape_pod4/station
icon_state = "shuttle2"
/area/shuttle/escape_pod4/centcom
icon_state = "shuttle"
/area/shuttle/escape_pod4/transit
icon_state = "shuttle"
/area/shuttle/escape_pod5
name = "\improper Escape Pod Five"
music = "music/escape.ogg"
/area/shuttle/escape_pod5/station
icon_state = "shuttle2"
/area/shuttle/escape_pod5/centcom
icon_state = "shuttle"
/area/shuttle/escape_pod5/transit
icon_state = "shuttle"
/area/shuttle/escape_pod6
name = "\improper Escape Pod Six"
music = "music/escape.ogg"
/area/shuttle/escape_pod6/station
icon_state = "shuttle2"
/area/shuttle/escape_pod6/centcom
icon_state = "shuttle"
/area/shuttle/escape_pod6/transit
icon_state = "shuttle"
/area/shuttle/large_escape_pod1
name = "\improper Large Escape Pod One"
music = "music/escape.ogg"
/area/shuttle/large_escape_pod1/station
icon_state = "shuttle2"
/area/shuttle/large_escape_pod1/centcom
icon_state = "shuttle"
/area/shuttle/large_escape_pod1/transit
icon_state = "shuttle"
/area/shuttle/large_escape_pod2
name = "\improper Large Escape Pod Two"
music = "music/escape.ogg"
/area/shuttle/large_escape_pod2/station
icon_state = "shuttle2"
/area/shuttle/large_escape_pod2/centcom
icon_state = "shuttle"
/area/shuttle/large_escape_pod2/transit
icon_state = "shuttle"
/area/shuttle/cryo
name = "\improper Cryogenic Storage"
/area/shuttle/cryo/station
icon_state = "shuttle2"
base_turf = /turf/simulated/mineral/floor/ignore_mapgen
/area/shuttle/cryo/centcom
icon_state = "shuttle"
/area/shuttle/cryo/transit
icon_state = "shuttle"
/area/shuttle/mining
name = "\improper Mining Elevator"
music = "music/escape.ogg"
dynamic_lighting = 0
base_turf = /turf/simulated/mineral/floor/ignore_mapgen
/area/shuttle/mining/station
icon_state = "shuttle2"
/area/shuttle/mining/outpost
icon_state = "shuttle"
/area/shuttle/transport1/centcom
icon_state = "shuttle"
name = "\improper Transport Shuttle CentCom"
@@ -286,54 +180,15 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "red"
dynamic_lighting = 0
/area/shuttle/trade/centcom
name = "\improper Trade Shuttle CentCom"
icon_state = "shuttlered"
/area/shuttle/trade/station
name = "\improper Trade Shuttle"
icon_state = "shuttlered"
/area/shuttle/thunderdome
name = "honk"
/area/shuttle/thunderdome/grnshuttle
name = "\improper Thunderdome GRN Shuttle"
icon_state = "green"
/area/shuttle/thunderdome/grnshuttle/dome
name = "\improper GRN Shuttle"
icon_state = "shuttlegrn"
/area/shuttle/thunderdome/grnshuttle/station
name = "\improper GRN Station"
icon_state = "shuttlegrn2"
/area/shuttle/thunderdome/redshuttle
name = "\improper Thunderdome RED Shuttle"
icon_state = "red"
/area/shuttle/thunderdome/redshuttle/dome
name = "\improper RED Shuttle"
icon_state = "shuttlered"
/area/shuttle/thunderdome/redshuttle/station
name = "\improper RED Station"
icon_state = "shuttlered2"
// === Trying to remove these areas:
/area/shuttle/research
name = "\improper Research Elevator"
music = "music/escape.ogg"
dynamic_lighting = 0
base_turf = /turf/simulated/mineral/floor/ignore_mapgen
/area/shuttle/research/station
icon_state = "shuttle2"
/area/shuttle/research/outpost
icon_state = "shuttle"
/area/airtunnel1/ // referenced in airtunnel.dm:759
/area/dummy/ // Referenced in engine.dm:261
@@ -2040,17 +1895,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "\improper Cargo Mining Dock"
icon_state = "mining"
/area/supply/station
name = "Supply Shuttle"
icon_state = "shuttle3"
requires_power = 0
base_turf = /turf/space
/area/supply/dock
name = "Supply Shuttle"
icon_state = "shuttle3"
requires_power = 0
base_turf = /turf/space
// SCIENCE
+6 -21
View File
@@ -1,23 +1,8 @@
//TFF 28/8/19 - cleanup of areas placement - removes all but rogueminer_vr stuff.
/area/shuttle/belter/station
name = "Belter Shuttle Landed"
/area/shuttle/belter
name = "Belter Shuttle"
icon_state = "shuttle2"
base_turf = /turf/simulated/floor/tiled/asteroid_steel/airless
/area/shuttle/belter/belt //Don't use this one, use a subtype
name = "Belter Shuttle Holding Position"
icon_state = "shuttle2"
//Placeholders
/area/shuttle/belter/belt/zone1
/area/shuttle/belter/belt/zone2
/area/shuttle/belter/belt/zone3
/area/shuttle/belter/belt/zone4
/area/shuttle/belter/transit
name = "Belter Shuttle Warp"
icon_state = "shuttle"
//Rouguelike Mining
/area/asteroid/rogue
@@ -28,22 +13,22 @@
/area/asteroid/rogue/zone1
name = "Asteroid Belt Zone 1"
icon_state = "red2"
shuttle_area = /area/shuttle/belter/belt/zone1
//shuttle_area = /area/shuttle/belter/belt/zone1
/area/asteroid/rogue/zone2
name = "Asteroid Belt Zone 2"
icon_state = "blue2"
shuttle_area = /area/shuttle/belter/belt/zone2
//shuttle_area = /area/shuttle/belter/belt/zone2
/area/asteroid/rogue/zone3
name = "Asteroid Belt Zone 3"
icon_state = "blue2"
shuttle_area = /area/shuttle/belter/belt/zone3
//shuttle_area = /area/shuttle/belter/belt/zone3
/area/asteroid/rogue/zone4
name = "Asteroid Belt Zone 4"
icon_state = "red2"
shuttle_area = /area/shuttle/belter/belt/zone4
//shuttle_area = /area/shuttle/belter/belt/zone4
/area/engineering/engine_gas
name = "\improper Engine Gas Storage"
+25
View File
@@ -71,6 +71,31 @@
power_change() // all machines set to current power level, also updates lighting icon
return INITIALIZE_HINT_LATELOAD
// Changes the area of T to A. Do not do this manually.
// Area is expected to be a non-null instance.
/proc/ChangeArea(var/turf/T, var/area/A)
if(!istype(A))
CRASH("Area change attempt failed: invalid area supplied.")
var/area/old_area = get_area(T)
if(old_area == A)
return
// NOTE: BayStation calles area.Exited/Entered for the TURF T. So far we don't do that.s
// NOTE: There probably won't be any atoms in these turfs, but just in case we should call these procs.
A.contents.Add(T)
if(old_area)
// Handle dynamic lighting update if
if(T.dynamic_lighting && old_area.dynamic_lighting != A.dynamic_lighting)
if(A.dynamic_lighting)
T.lighting_build_overlay()
else
T.lighting_clear_overlay()
for(var/atom/movable/AM in T)
old_area.Exited(AM, A)
for(var/atom/movable/AM in T)
A.Entered(AM, old_area)
for(var/obj/machinery/M in T)
M.power_change()
/area/proc/get_contents()
return contents
+164
View File
@@ -0,0 +1,164 @@
//
// Shuttles formerly required at least two areas in a subgroup if you want to move a shuttle from one
// place to another. Since shuttles now used landmarks instead these areas are deprecated!
// They are left here for the moment in order to make existing maps loadable, but should be phased out.
//
/area/shuttle/arrival/pre_game
icon_state = "shuttle2"
/area/shuttle/arrival/station
icon_state = "shuttle"
dynamic_lighting = 0
ambience = AMBIENCE_ARRIVALS
/area/shuttle/escape/station
name = "\improper Emergency Shuttle Station"
icon_state = "shuttle2"
dynamic_lighting = 0
/area/shuttle/escape/centcom
name = "\improper Emergency Shuttle CentCom"
icon_state = "shuttle"
/area/shuttle/escape/transit // the area to pass through for 3 minute transit
name = "\improper Emergency Shuttle Transit"
icon_state = "shuttle"
/area/shuttle/escape_pod1/station
icon_state = "shuttle2"
/area/shuttle/escape_pod1/centcom
icon_state = "shuttle"
/area/shuttle/escape_pod1/transit
icon_state = "shuttle"
/area/shuttle/escape_pod2/station
icon_state = "shuttle2"
/area/shuttle/escape_pod2/centcom
icon_state = "shuttle"
/area/shuttle/escape_pod2/transit
icon_state = "shuttle"
/area/shuttle/escape_pod3/station
icon_state = "shuttle2"
/area/shuttle/escape_pod3/centcom
icon_state = "shuttle"
/area/shuttle/escape_pod3/transit
icon_state = "shuttle"
/area/shuttle/escape_pod4/station
icon_state = "shuttle2"
/area/shuttle/escape_pod4/centcom
icon_state = "shuttle"
/area/shuttle/escape_pod4/transit
icon_state = "shuttle"
/area/shuttle/escape_pod5/station
icon_state = "shuttle2"
/area/shuttle/escape_pod5/centcom
icon_state = "shuttle"
/area/shuttle/escape_pod5/transit
icon_state = "shuttle"
/area/shuttle/escape_pod6/station
icon_state = "shuttle2"
/area/shuttle/escape_pod6/centcom
icon_state = "shuttle"
/area/shuttle/escape_pod6/transit
icon_state = "shuttle"
/area/shuttle/large_escape_pod1/station
icon_state = "shuttle2"
/area/shuttle/large_escape_pod1/centcom
icon_state = "shuttle"
/area/shuttle/large_escape_pod1/transit
icon_state = "shuttle"
/area/shuttle/large_escape_pod2/station
icon_state = "shuttle2"
/area/shuttle/large_escape_pod2/centcom
icon_state = "shuttle"
/area/shuttle/large_escape_pod2/transit
icon_state = "shuttle"
/area/shuttle/cryo/station
icon_state = "shuttle2"
base_turf = /turf/simulated/mineral/floor/ignore_mapgen
/area/shuttle/cryo/centcom
icon_state = "shuttle"
/area/shuttle/cryo/transit
icon_state = "shuttle"
/area/shuttle/mining/station
icon_state = "shuttle2"
/area/shuttle/mining/outpost
icon_state = "shuttle"
/area/shuttle/trade/centcom
name = "\improper Trade Shuttle CentCom"
icon_state = "shuttlered"
/area/shuttle/trade/station
name = "\improper Trade Shuttle"
icon_state = "shuttlered"
/area/shuttle/thunderdome/grnshuttle
name = "\improper Thunderdome GRN Shuttle"
icon_state = "green"
/area/shuttle/thunderdome/grnshuttle/dome
name = "\improper GRN Shuttle"
icon_state = "shuttlegrn"
/area/shuttle/thunderdome/grnshuttle/station
name = "\improper GRN Station"
icon_state = "shuttlegrn2"
/area/shuttle/thunderdome/redshuttle
name = "\improper Thunderdome RED Shuttle"
icon_state = "red"
/area/shuttle/thunderdome/redshuttle/dome
name = "\improper RED Shuttle"
icon_state = "shuttlered"
/area/shuttle/thunderdome/redshuttle/station
name = "\improper RED Station"
icon_state = "shuttlered2"
/area/shuttle/research/station
icon_state = "shuttle2"
/area/shuttle/research/outpost
icon_state = "shuttle"
/area/supply/station
name = "Supply Shuttle"
icon_state = "shuttle3"
requires_power = 0
base_turf = /turf/space
/area/supply/dock
name = "Supply Shuttle"
icon_state = "shuttle3"
requires_power = 0
base_turf = /turf/space
+3
View File
@@ -519,6 +519,9 @@
return TRUE
return FALSE
/atom/proc/is_incorporeal()
return FALSE
/atom/proc/drop_location()
var/atom/L = loc
if(!L)
+1 -1
View File
@@ -453,7 +453,7 @@
if(z in using_map.sealed_levels)
return
if(config.use_overmap)
if(using_map.use_overmap)
overmap_spacetravel(get_turf(src), src)
return
+2 -22
View File
@@ -132,22 +132,6 @@
anchored = 1.0
var/spawnable = null
/obj/effect/gateway/Bumped(mob/M as mob|obj)
spawn(0)
return
return
/obj/effect/gateway/Crossed(AM as mob|obj)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = AM
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
spawn(0)
return
return
/obj/effect/gateway/active
light_range=5
light_color="#ff0000"
@@ -176,12 +160,8 @@
qdel(src)
/obj/effect/gateway/active/Crossed(var/atom/A)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = A
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
if(A.is_incorporeal())
return
if(!istype(A, /mob/living))
return
+2 -1
View File
@@ -48,8 +48,9 @@ var/global/datum/controller/gameticker/ticker
send2mainirc("Server lobby is loaded and open at byond://[config.serverurl ? config.serverurl : (config.server ? config.server : "[world.address]:[world.port]")]")
pregame_timeleft = config.pregame_time
do
pregame_timeleft = 180
to_chat(world, "<B><FONT color='blue'>Welcome to the pregame lobby!</FONT></B>")
to_chat(world, "Please set up your character and select ready. The round will start in [pregame_timeleft] seconds.")
while(current_state == GAME_STATE_PREGAME)
+4 -4
View File
@@ -56,7 +56,7 @@
var/orders[0]
var/receipts[0]
var/datum/shuttle/ferry/supply/shuttle = supply_controller.shuttle
var/datum/shuttle/autodock/ferry/supply/shuttle = supply_controller.shuttle
if(shuttle)
if(shuttle.has_arrive_time())
shuttle_status["location"] = "In transit"
@@ -66,8 +66,8 @@
else
shuttle_status["time"] = 0
if(shuttle.at_station())
if(shuttle.docking_controller)
switch(shuttle.docking_controller.get_docking_status())
if(shuttle.shuttle_docking_controller)
switch(shuttle.shuttle_docking_controller.get_docking_status())
if("docked")
shuttle_status["location"] = "Docked"
shuttle_status["mode"] = SUP_SHUTTLE_DOCKED
@@ -192,7 +192,7 @@
if(!supply_controller)
to_world_log("## ERROR: The supply_controller datum is missing.")
return
var/datum/shuttle/ferry/supply/shuttle = supply_controller.shuttle
var/datum/shuttle/autodock/ferry/supply/shuttle = supply_controller.shuttle
if (!shuttle)
to_world_log("## ERROR: The supply shuttle datum is missing.")
return
+8
View File
@@ -178,6 +178,14 @@
icon = 'icons/obj/doors/Doorext.dmi'
assembly_type = /obj/structure/door_assembly/door_assembly_ext
/obj/machinery/door/airlock/external/glass/bolted
icon_state = "door_locked" // So it looks visibly bolted in map editor
locked = 1
// For convenience in making docking ports: one that is pre-bolted with frequency set!
/obj/machinery/door/airlock/external/glass/bolted/cycling
frequency = 1379
/obj/machinery/door/airlock/glass_external
name = "External Airlock"
icon = 'icons/obj/doors/Doorextglass.dmi'
@@ -2,6 +2,7 @@
/obj/machinery/embedded_controller/radio/airlock
// Setup parameters only
radio_filter = RADIO_AIRLOCK
program = /datum/computer/file/embedded_program/airlock
var/tag_exterior_door
var/tag_interior_door
var/tag_airpump
@@ -11,11 +12,22 @@
var/tag_airlock_mech_sensor
var/tag_shuttle_mech_sensor
var/tag_secure = 0
var/list/dummy_terminals = list()
var/cycle_to_external_air = 0
/obj/machinery/embedded_controller/radio/airlock/Initialize()
. = ..()
program = new/datum/computer/file/embedded_program/airlock(src)
/obj/machinery/embedded_controller/radio/airlock/Destroy()
// TODO - Leshana - Implement dummy terminals
//for(var/thing in dummy_terminals)
// var/obj/machinery/dummy_airlock_controller/dummy = thing
// dummy.master_controller = null
//dummy_terminals.Cut()
return ..()
/obj/machinery/embedded_controller/radio/airlock/CanUseTopic(var/mob/user)
if(!allowed(user))
return min(STATUS_UPDATE, ..())
else
return ..()
//Advanced airlock controller for when you want a more versatile airlock controller - useful for turning simple access control rooms into airlocks
/obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller
@@ -37,43 +49,20 @@
if (!ui)
ui = new(user, src, ui_key, "advanced_airlock_console.tmpl", name, 470, 290)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller/Topic(href, href_list)
if(..())
if((. = ..()))
return
usr.set_machine(src)
src.add_fingerprint(usr)
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
if("cycle_ext")
clean = 1
if("cycle_int")
clean = 1
if("force_ext")
clean = 1
if("force_int")
clean = 1
if("abort")
clean = 1
if("purge")
clean = 1
if("secure")
clean = 1
if(clean)
program.receive_user_command(href_list["command"])
if("cycle_ext", "cycle_int", "force_ext", "force_int", "abort", "purge", "secure")
program.receive_user_command(href_list["command"])
return 1
//Airlock controller for airlock control - most airlocks on the station use this
/obj/machinery/embedded_controller/radio/airlock/airlock_controller
name = "Airlock Controller"
@@ -90,23 +79,16 @@
)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "simple_airlock_console.tmpl", name, 470, 290)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/airlock/airlock_controller/Topic(href, href_list)
if(..())
if((. = ..()))
return
usr.set_machine(src)
src.add_fingerprint(usr)
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
if("cycle_ext")
@@ -125,7 +107,6 @@
return 1
//Access controller for door control - used in virology and the like
/obj/machinery/embedded_controller/radio/airlock/access_controller
icon = 'icons/obj/airlock_machines.dmi'
@@ -154,23 +135,16 @@
)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "door_access_console.tmpl", name, 330, 220)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/airlock/access_controller/Topic(href, href_list)
if(..())
if((. = ..()))
return
usr.set_machine(src)
src.add_fingerprint(usr)
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
if("cycle_ext_door")
@@ -0,0 +1,51 @@
// Provides remote access to a controller (since they must be unique).
/obj/machinery/dummy_airlock_controller
name = "airlock control terminal"
icon = 'icons/obj/airlock_machines.dmi'
icon_state = "airlock_control_standby"
layer = ABOVE_OBJ_LAYER
var/id_tag
var/datum/topic_state/remote/remote_state
var/obj/machinery/embedded_controller/radio/airlock/master_controller
/obj/machinery/dummy_airlock_controller/process()
if(master_controller)
appearance = master_controller
. = ..()
/obj/machinery/dummy_airlock_controller/Initialize()
. = ..()
if(id_tag)
for(var/obj/machinery/embedded_controller/radio/airlock/_master in SSmachines.machinery)
if(_master.id_tag == id_tag)
master_controller = _master
master_controller.dummy_terminals += src
break
if(!master_controller)
qdel(src)
else
remote_state = new /datum/topic_state/remote(src, master_controller)
/obj/machinery/dummy_airlock_controller/Destroy()
if(master_controller)
master_controller.dummy_terminals -= src
if(remote_state)
qdel(remote_state)
remote_state = null
return ..()
/obj/machinery/dummy_airlock_controller/interface_interact(var/mob/user)
open_remote_ui(user)
return TRUE
/obj/machinery/dummy_airlock_controller/proc/open_remote_ui(var/mob/user)
if(master_controller)
appearance = master_controller
return master_controller.ui_interact(user, state = remote_state)
/obj/machinery/dummy_airlock_controller/powered(var/chan = -1, var/area/check_area = null)
if(master_controller)
var/area/A = get_area(master_controller)
return master_controller.powered(chan, A)
return ..()
@@ -1,8 +1,17 @@
/*
* NOTE - This file defines both these datums: Yes, you read that right. Its confusing. Lets try and break it down.
* /datum/computer/file/embedded_program/docking/airlock
* - A docking controller for an airlock based docking port
* /datum/computer/file/embedded_program/airlock/docking
* - An extension to the normal airlock program allows disabling of the regular airlock functions when docking
*/
//a docking port based on an airlock
/obj/machinery/embedded_controller/radio/airlock/docking_port
name = "docking port controller"
var/datum/computer/file/embedded_program/airlock/docking/airlock_program
var/datum/computer/file/embedded_program/docking/airlock/docking_program
var/display_name // For mappers to override docking_program.display_name (how would it show up on docking monitoring program)
tag_secure = 1
/obj/machinery/embedded_controller/radio/airlock/docking_port/Initialize()
@@ -10,9 +19,25 @@
airlock_program = new/datum/computer/file/embedded_program/airlock/docking(src)
docking_program = new/datum/computer/file/embedded_program/docking/airlock(src, airlock_program)
program = docking_program
if(display_name)
docking_program.display_name = display_name
/obj/machinery/embedded_controller/radio/airlock/docking_port/attackby(obj/item/W, mob/user)
if(istype(W,/obj/item/device/multitool)) //give them part of code, would take few tries to get full
var/datum/computer/file/embedded_program/docking/airlock/docking_program = program
var/code = docking_program.docking_codes
if(!code)
code = "N/A"
else
code = stars(code)
to_chat(user, "[W]'s screen displays '[code]'")
else
..()
/obj/machinery/embedded_controller/radio/airlock/docking_port/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/datum/computer/file/embedded_program/docking/airlock/docking_program = program
var/datum/computer/file/embedded_program/airlock/docking/airlock_program = docking_program.airlock_program
data = list(
"chamber_pressure" = round(airlock_program.memory["chamber_sensor_pressure"]),
@@ -22,6 +47,8 @@
"docking_status" = docking_program.get_docking_status(),
"airlock_disabled" = !(docking_program.undocked() || docking_program.override_enabled),
"override_enabled" = docking_program.override_enabled,
"docking_codes" = docking_program.docking_codes,
"name" = docking_program.get_name()
)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
@@ -33,12 +60,9 @@
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/airlock/docking_port/Topic(href, href_list)
if(..())
if((. = ..()))
return
usr.set_machine(src)
src.add_fingerprint(usr)
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
if("cycle_ext")
@@ -60,11 +84,13 @@
return 1
///////////////////////////////////////////////////////////////////////////////
//A docking controller for an airlock based docking port
//
/datum/computer/file/embedded_program/docking/airlock
var/datum/computer/file/embedded_program/airlock/docking/airlock_program
/datum/computer/file/embedded_program/docking/airlock/New(var/obj/machinery/embedded_controller/M, var/datum/computer/file/embedded_program/airlock/docking/A)
..(M)
airlock_program = A
@@ -76,10 +102,10 @@
disable_override()
else
enable_override()
return
return TRUE
..(command)
airlock_program.receive_user_command(command) //pass along to subprograms
. = ..(command)
. = airlock_program.receive_user_command(command) || . //pass along to subprograms; bypass shortcircuit
/datum/computer/file/embedded_program/docking/airlock/process()
airlock_program.process()
@@ -91,7 +117,7 @@
//tell the docking port to start getting ready for docking - e.g. pressurize
/datum/computer/file/embedded_program/docking/airlock/prepare_for_docking()
airlock_program.begin_cycle_in()
airlock_program.begin_dock_cycle()
//are we ready for docking?
/datum/computer/file/embedded_program/docking/airlock/ready_for_docking()
@@ -99,14 +125,14 @@
//we are docked, open the doors or whatever.
/datum/computer/file/embedded_program/docking/airlock/finish_docking()
airlock_program.enable_mech_regulators()
airlock_program.enable_mech_regulation()
airlock_program.open_doors()
//tell the docking port to start getting ready for undocking - e.g. close those doors.
/datum/computer/file/embedded_program/docking/airlock/prepare_for_undocking()
airlock_program.stop_cycling()
airlock_program.close_doors()
airlock_program.disable_mech_regulators()
airlock_program.disable_mech_regulation()
//are we ready for undocking?
/datum/computer/file/embedded_program/docking/airlock/ready_for_undocking()
@@ -114,20 +140,22 @@
var/int_closed = airlock_program.check_interior_door_secured()
return (ext_closed || int_closed)
///////////////////////////////////////////////////////////////////////////////
//An airlock controller to be used by the airlock-based docking port controller.
//Same as a regular airlock controller but allows disabling of the regular airlock functions when docking
//
/datum/computer/file/embedded_program/airlock/docking
var/datum/computer/file/embedded_program/docking/airlock/master_prog
/datum/computer/file/embedded_program/airlock/docking/Destroy()
if(master_prog)
master_prog.airlock_program = null
master_prog = null
return ..()
/datum/computer/file/embedded_program/airlock/docking/receive_user_command(command)
if (master_prog.undocked() || master_prog.override_enabled) //only allow the port to be used as an airlock if nothing is docked here or the override is enabled
..(command)
/datum/computer/file/embedded_program/airlock/docking/proc/enable_mech_regulators()
enable_mech_regulation()
/datum/computer/file/embedded_program/airlock/docking/proc/disable_mech_regulators()
disable_mech_regulation()
return ..(command)
/datum/computer/file/embedded_program/airlock/docking/proc/open_doors()
toggleDoor(memory["interior_status"], tag_interior_door, memory["secure"], "open")
@@ -2,21 +2,15 @@
//this is the master controller, that things will try to dock with.
/obj/machinery/embedded_controller/radio/docking_port_multi
name = "docking port controller"
program = /datum/computer/file/embedded_program/docking/multi
var/child_tags_txt
var/child_names_txt
var/list/child_names = list()
var/datum/computer/file/embedded_program/docking/multi/docking_program
/obj/machinery/embedded_controller/radio/docking_port_multi/Initialize()
. = ..()
docking_program = new/datum/computer/file/embedded_program/docking/multi(src)
program = docking_program
var/list/names = splittext(child_names_txt, ";")
var/list/tags = splittext(child_tags_txt, ";")
if (names.len == tags.len)
for (var/i = 1; i <= tags.len; i++)
child_names[tags[i]] = names[i]
@@ -24,6 +18,7 @@
/obj/machinery/embedded_controller/radio/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/datum/computer/file/embedded_program/docking/multi/docking_program = program // Cast to proper type
var/list/airlocks[child_names.len]
var/i = 1
@@ -44,24 +39,21 @@
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/docking_port_multi/Topic(href, href_list)
return
return 1 // Apparently we swallow all input (this is corrected legacy code)
//a docking port based on an airlock
// This is the actual controller that will be commanded by the master defined above
/obj/machinery/embedded_controller/radio/airlock/docking_port_multi
name = "docking port controller"
program = /datum/computer/file/embedded_program/airlock/multi_docking
var/master_tag //for mapping
var/datum/computer/file/embedded_program/airlock/multi_docking/airlock_program
tag_secure = 1
/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/Initialize()
. = ..()
airlock_program = new/datum/computer/file/embedded_program/airlock/multi_docking(src)
program = airlock_program
/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/datum/computer/file/embedded_program/airlock/multi_docking/airlock_program // Cast to proper type
data = list(
"chamber_pressure" = round(airlock_program.memory["chamber_sensor_pressure"]),
@@ -82,12 +74,9 @@
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/Topic(href, href_list)
if(..())
if((. = ..()))
return
usr.set_machine(src)
src.add_fingerprint(usr)
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
if("cycle_ext")
@@ -52,8 +52,8 @@
tag_interior_door = controller.tag_interior_door? controller.tag_interior_door : "[id_tag]_inner"
tag_airpump = controller.tag_airpump? controller.tag_airpump : "[id_tag]_pump"
tag_chamber_sensor = controller.tag_chamber_sensor? controller.tag_chamber_sensor : "[id_tag]_sensor"
tag_exterior_sensor = controller.tag_exterior_sensor
tag_interior_sensor = controller.tag_interior_sensor
tag_exterior_sensor = controller.tag_exterior_sensor || "[id_tag]_exterior_sensor"
tag_interior_sensor = controller.tag_interior_sensor || "[id_tag]_interior_sensor"
tag_airlock_mech_sensor = controller.tag_airlock_mech_sensor? controller.tag_airlock_mech_sensor : "[id_tag]_airlock_mech"
tag_shuttle_mech_sensor = controller.tag_shuttle_mech_sensor? controller.tag_shuttle_mech_sensor : "[id_tag]_shuttle_mech"
memory["secure"] = controller.tag_secure
@@ -117,6 +117,7 @@
/datum/computer/file/embedded_program/airlock/receive_user_command(command)
var/shutdown_pump = 0
. = TRUE
switch(command)
if("cycle_ext")
//If airlock is already cycled in this direction, just toggle the doors.
@@ -163,6 +164,8 @@
else
signalDoor(tag_interior_door, "unlock")
signalDoor(tag_exterior_door, "unlock")
else
. = FALSE
if(shutdown_pump)
signalPump(tag_airpump, 0) //send a signal to stop pressurizing
@@ -273,6 +276,9 @@
target_state = TARGET_INOPEN
memory["purge"] = cycle_to_external_air
/datum/computer/file/embedded_program/airlock/proc/begin_dock_cycle()
state = STATE_IDLE
target_state = TARGET_INOPEN
/datum/computer/file/embedded_program/airlock/proc/begin_cycle_out()
state = STATE_IDLE
target_state = TARGET_OUTOPEN
@@ -12,51 +12,51 @@
/*
*** STATE TABLE ***
MODE_CLIENT|STATE_UNDOCKED sent a request for docking and now waiting for a reply.
MODE_CLIENT|STATE_DOCKING server told us they are OK to dock, waiting for our docking port to be ready.
MODE_CLIENT|STATE_DOCKED idle - docked as client.
MODE_CLIENT|STATE_UNDOCKING we are either waiting for our docking port to be ready or for the server to give us the OK to finish undocking.
MODE_SERVER|STATE_UNDOCKED should never happen.
MODE_SERVER|STATE_DOCKING someone requested docking, we are waiting for our docking port to be ready.
MODE_SERVER|STATE_DOCKED idle - docked as server
MODE_SERVER|STATE_UNDOCKING client requested undocking, we are waiting for our docking port to be ready.
MODE_NONE|STATE_UNDOCKED idle - not docked.
MODE_NONE|anything else should never happen.
*** Docking Signals ***
Docking
Client sends request_dock
Server sends confirm_dock to say that yes, we will serve your request
When client is ready, sends confirm_dock
Server sends confirm_dock back to indicate that docking is complete
Undocking
Client sends request_undock
When client is ready, sends confirm_undock
Server sends confirm_undock back to indicate that docking is complete
Note that in both cases each side exchanges confirm_dock before the docking operation is considered done.
The client first sends a confirm message to indicate it is ready, and then finally the server will send it's
The client first sends a confirm message to indicate it is ready, and then finally the server will send it's
confirm message to indicate that the operation is complete.
Note also that when docking, the server sends an additional confirm message. This is because before docking,
the server and client do not have a defined relationship. Before undocking, the server and client are already
related to each other, thus the extra confirm message is not needed.
*** Override, what is it? ***
The purpose of enabling the override is to prevent the docking program from automatically doing things with the docking port when docking or undocking.
Maybe the shuttle is full of plamsa/phoron for some reason, and you don't want the door to automatically open, or the airlock to cycle.
This means that the prepare_for_docking/undocking and finish_docking/undocking procs don't get called.
The docking controller will still check the state of the docking port, and thus prevent the shuttle from launching unless they force the launch (handling forced
launches is not the docking controller's responsibility). In this case it is up to the players to manually get the docking port into a good state to undock
launches is not the docking controller's responsibility). In this case it is up to the players to manually get the docking port into a good state to undock
(which usually just means closing and locking the doors).
In line with this, docking controllers should prevent players from manually doing things when the override is NOT enabled.
*/
@@ -67,27 +67,31 @@
var/control_mode = MODE_NONE
var/response_sent = 0 //so we don't spam confirmation messages
var/resend_counter = 0 //for periodically resending confirmation messages in case they are missed
var/override_enabled = 0 //when enabled, do not open/close doors or cycle airlocks and wait for the player to do it manually
var/received_confirm = 0 //for undocking, whether the server has recieved a confirmation from the client
var/docking_codes //would only allow docking when receiving signal with these, if set
var/display_name //Override the name shown on docking monitoring program; defaults to area name + coordinates if unset
/datum/computer/file/embedded_program/docking/New()
..()
var/datum/existing = locate(id_tag) //in case a datum already exists with our tag
if(existing)
existing.tag = null //take it from them
tag = id_tag //Greatly simplifies shuttle initialization
if(id_tag)
if(SSshuttles.docking_registry[id_tag])
crash_with("Docking controller tag [id_tag] had multiple associated programs.")
SSshuttles.docking_registry[id_tag] = src
/datum/computer/file/embedded_program/docking/Destroy()
SSshuttles.docking_registry -= id_tag
return ..()
/datum/computer/file/embedded_program/docking/receive_signal(datum/signal/signal, receive_method, receive_param)
var/receive_tag = signal.data["tag"] //for docking signals, this is the sender id
var/command = signal.data["command"]
var/recipient = signal.data["recipient"] //the intended recipient of the docking signal
if (recipient != id_tag)
return //this signal is not for us
switch (command)
if ("confirm_dock")
if (control_mode == MODE_CLIENT && dock_state == STATE_UNDOCKED && receive_tag == tag_target)
@@ -95,7 +99,7 @@
broadcast_docking_status()
if (!override_enabled)
prepare_for_docking()
else if (control_mode == MODE_CLIENT && dock_state == STATE_DOCKING && receive_tag == tag_target)
dock_state = STATE_DOCKED
broadcast_docking_status()
@@ -104,19 +108,27 @@
response_sent = 0
else if (control_mode == MODE_SERVER && dock_state == STATE_DOCKING && receive_tag == tag_target) //client just sent us the confirmation back, we're done with the docking process
received_confirm = 1
if ("request_dock")
if (control_mode == MODE_NONE && dock_state == STATE_UNDOCKED)
tag_target = receive_tag
if(docking_codes)
var/code = signal.data["code"]
if(code != docking_codes)
testing("Controller [id_tag] got request_dock but code:[code] != docking_codes:[docking_codes]")
return
control_mode = MODE_SERVER
dock_state = STATE_DOCKING
broadcast_docking_status()
tag_target = receive_tag
if (!override_enabled)
prepare_for_docking()
send_docking_command(tag_target, "confirm_dock") //acknowledge the request
if ("confirm_undock")
if (control_mode == MODE_CLIENT && dock_state == STATE_UNDOCKING && receive_tag == tag_target)
if (!override_enabled)
@@ -129,7 +141,7 @@
if (control_mode == MODE_SERVER && dock_state == STATE_DOCKED && receive_tag == tag_target)
dock_state = STATE_UNDOCKING
broadcast_docking_status()
if (!override_enabled)
prepare_for_undocking()
@@ -145,38 +157,38 @@
if (!response_sent)
send_docking_command(tag_target, "confirm_dock") //tell the server we're ready
response_sent = 1
else if (control_mode == MODE_SERVER && received_confirm)
send_docking_command(tag_target, "confirm_dock") //tell the client we are done docking.
dock_state = STATE_DOCKED
broadcast_docking_status()
if (!override_enabled)
finish_docking() //server done docking!
response_sent = 0
received_confirm = 0
if (STATE_UNDOCKING)
if (ready_for_undocking())
if (control_mode == MODE_CLIENT)
if (!response_sent)
send_docking_command(tag_target, "confirm_undock") //tell the server we are OK to undock.
response_sent = 1
else if (control_mode == MODE_SERVER && received_confirm)
send_docking_command(tag_target, "confirm_undock") //tell the client we are done undocking.
if (!override_enabled)
finish_undocking()
reset() //server is done undocking!
if (response_sent || resend_counter > 0)
resend_counter++
if (resend_counter >= MESSAGE_RESEND_TIME || (dock_state != STATE_DOCKING && dock_state != STATE_UNDOCKING))
response_sent = 0
resend_counter = 0
//handle invalid states
if (control_mode == MODE_NONE && dock_state != STATE_UNDOCKED)
if (tag_target)
@@ -189,22 +201,22 @@
/datum/computer/file/embedded_program/docking/proc/initiate_docking(var/target)
if (dock_state != STATE_UNDOCKED || control_mode == MODE_SERVER) //must be undocked and not serving another request to begin a new docking handshake
return
tag_target = target
control_mode = MODE_CLIENT
send_docking_command(tag_target, "request_dock")
/datum/computer/file/embedded_program/docking/proc/initiate_undocking()
if (dock_state != STATE_DOCKED || control_mode != MODE_CLIENT) //must be docked and must be client to start undocking
return
dock_state = STATE_UNDOCKING
broadcast_docking_status()
if (!override_enabled)
prepare_for_undocking()
send_docking_command(tag_target, "request_undock")
//tell the docking port to start getting ready for docking - e.g. pressurize
@@ -240,7 +252,7 @@
/datum/computer/file/embedded_program/docking/proc/reset()
dock_state = STATE_UNDOCKED
broadcast_docking_status()
control_mode = MODE_NONE
tag_target = null
response_sent = 0
@@ -267,6 +279,7 @@
signal.data["tag"] = id_tag
signal.data["command"] = command
signal.data["recipient"] = recipient
signal.data["code"] = docking_codes
post_signal(signal)
/datum/computer/file/embedded_program/docking/proc/broadcast_docking_status()
@@ -283,6 +296,8 @@
if (STATE_UNDOCKING) return "undocking"
if (STATE_DOCKED) return "docked"
/datum/computer/file/embedded_program/docking/proc/get_name()
return display_name ? display_name : "[get_area(master)] ([master.x], [master.y])"
#undef STATE_UNDOCKED
#undef STATE_DOCKING
@@ -1,18 +1,20 @@
/obj/machinery/embedded_controller
var/datum/computer/file/embedded_program/program //the currently executing program
name = "Embedded Controller"
anchored = 1
use_power = 1
idle_power_usage = 10
var/datum/computer/file/embedded_program/program //the currently executing program
var/on = 1
obj/machinery/embedded_controller/radio/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
..()
/obj/machinery/embedded_controller/Initialize()
if(ispath(program))
program = new program(src)
return ..()
/obj/machinery/embedded_controller/Destroy()
if(istype(program))
qdel(program) // the program will clear the ref in its Destroy
return ..()
/obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line)
return 0
@@ -24,6 +26,17 @@ obj/machinery/embedded_controller/radio/Destroy()
program.receive_signal(signal, receive_method, receive_param)
//spawn(5) program.process() //no, program.process sends some signals and machines respond and we here again and we lag -rastaf0
/obj/machinery/embedded_controller/Topic(href, href_list)
if((. = ..()))
return
if(usr)
usr.set_machine(src)
src.add_fingerprint(usr)
// We would now pass it to the program, except that some of our embedded controller types want to block certain commands.
// Until/unless that is refactored differently, we rely on subtypes to pass it on.
//if(program)
// return program.receive_user_command(href_list["command"])
/obj/machinery/embedded_controller/process()
if(program)
program.process()
@@ -40,14 +53,16 @@ obj/machinery/embedded_controller/radio/Destroy()
src.ui_interact(user)
/obj/machinery/embedded_controller/ui_interact()
return
//
// Embedded controller with a radio! (Most things (All things?) use this)
//
/obj/machinery/embedded_controller/radio
icon = 'icons/obj/airlock_machines.dmi'
icon_state = "airlock_control_standby"
power_channel = ENVIRON
density = 0
unacidable = 1
var/id_tag
//var/radio_power_use = 50 //power used to xmit signals
@@ -55,11 +70,15 @@ obj/machinery/embedded_controller/radio/Destroy()
var/frequency = 1379
var/radio_filter = null
var/datum/radio_frequency/radio_connection
unacidable = 1
/obj/machinery/embedded_controller/radio/Initialize()
set_frequency(frequency) // Set it before parent instantiates program
. = ..()
set_frequency(frequency)
/obj/machinery/embedded_controller/radio/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
..()
/obj/machinery/embedded_controller/radio/update_icon()
if(on && program)
@@ -11,8 +11,15 @@
var/obj/machinery/embedded_controller/radio/R = M
id_tag = R.id_tag
/datum/computer/file/embedded_program/Destroy()
if(master)
master.program = null
master = null
return ..()
// Return TRUE if was a command for us, otherwise return FALSE (so controllers with multiple programs can try each in turn until one accepts)
/datum/computer/file/embedded_program/proc/receive_user_command(command)
return
return FALSE
/datum/computer/file/embedded_program/proc/receive_signal(datum/signal/signal, receive_method, receive_param)
return
@@ -1,16 +1,12 @@
//a docking port that uses a single door
/obj/machinery/embedded_controller/radio/simple_docking_controller
name = "docking hatch controller"
program = /datum/computer/file/embedded_program/docking/simple
var/tag_door
var/datum/computer/file/embedded_program/docking/simple/docking_program
/obj/machinery/embedded_controller/radio/simple_docking_controller/Initialize()
. = ..()
docking_program = new/datum/computer/file/embedded_program/docking/simple(src)
program = docking_program
/obj/machinery/embedded_controller/radio/simple_docking_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/datum/computer/file/embedded_program/docking/simple/docking_program = program // Cast to proper type
data = list(
"docking_status" = docking_program.get_docking_status(),
@@ -28,11 +24,8 @@
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/simple_docking_controller/Topic(href, href_list)
if(..())
return 1
usr.set_machine(src)
src.add_fingerprint(usr)
if((. = ..()))
return
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
@@ -44,8 +37,7 @@
if(clean)
program.receive_user_command(href_list["command"])
return 0
return
//A docking controller program for a simple door based docking port
/datum/computer/file/embedded_program/docking/simple
@@ -76,6 +68,7 @@
..(signal, receive_method, receive_param)
/datum/computer/file/embedded_program/docking/simple/receive_user_command(command)
. = TRUE
switch(command)
if("force_door")
if (override_enabled)
@@ -88,7 +81,8 @@
disable_override()
else
enable_override()
else
. = FALSE
/datum/computer/file/embedded_program/docking/simple/proc/signal_door(var/command)
var/datum/signal/signal = new
+1 -1
View File
@@ -210,7 +210,7 @@
return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]"
/obj/machinery/status_display/proc/get_supply_shuttle_timer()
var/datum/shuttle/ferry/supply/shuttle = supply_controller.shuttle
var/datum/shuttle/autodock/ferry/supply/shuttle = supply_controller.shuttle
if(!shuttle)
return "Error"
+1 -1
View File
@@ -6,7 +6,7 @@
message1 = "CARGO"
message2 = ""
var/datum/shuttle/ferry/supply/shuttle = supply_controller.shuttle
var/datum/shuttle/autodock/ferry/supply/shuttle = supply_controller.shuttle
if(!shuttle)
message2 = "Error"
else if(shuttle.has_arrive_time())
@@ -145,9 +145,6 @@
return 0
return 1
/obj/item/mecha_parts/mecha_equipment/proc/handle_movement_action() //Any modules that have special effects or needs when taking a step or floating through space.
return
/obj/item/mecha_parts/mecha_equipment/proc/action(atom/target)
return
@@ -0,0 +1,19 @@
/*
* File containing all the default 'handlers' for Exosuit equipment, hopefully to make all dynX calls extinct.
*/
// Used for impacting (thrown) objects, and damage value.
/obj/item/mecha_parts/mecha_equipment/proc/handle_ranged_contact(var/obj/A, var/inc_damage = 0)
return max(0, inc_damage)
// Used for melee strikes with an object, and a mob, and damage value.
/obj/item/mecha_parts/mecha_equipment/proc/handle_melee_contact(var/obj/item/weapon/W, var/mob/living/user, var/inc_damage = 0)
return max(0, inc_damage)
// Used for projectile impacts from bullet_act.
/obj/item/mecha_parts/mecha_equipment/proc/handle_projectile_contact(var/obj/item/projectile/Proj, var/inc_damage = 0)
return max(0, inc_damage)
// Used for on-movement actions.
/obj/item/mecha_parts/mecha_equipment/proc/handle_movement_action() //Any modules that have special effects or needs when taking a step or floating through space.
return
+26 -5
View File
@@ -11,6 +11,30 @@
equip_type = EQUIP_HULL
/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/get_equip_info()
if(!chassis) return
return "<span style=\"color:[equip_ready?"#0f0":"#f00"];\">*</span>&nbsp;[src.name]"
/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/handle_melee_contact(var/obj/item/weapon/W, var/mob/living/user, var/inc_damage = null)
if(!action_checks(user))
return inc_damage
chassis.log_message("Attacked by [W]. Attacker - [user]")
if(prob(chassis.deflect_chance*deflect_coeff))
to_chat(user, "<span class='danger'>\The [W] bounces off \the [chassis]'s armor.</span>")
chassis.log_append_to_last("Armor saved.")
inc_damage = 0
else
chassis.occupant_message("<span class='danger'>\The [user] hits [chassis] with [W].</span>")
user.visible_message("<span class='danger'>\The [user] hits [chassis] with [W].</span>", "<span class='danger'>You hit [src] with [W].</span>")
inc_damage *= damage_coeff
set_ready_state(0)
chassis.use_power(energy_drain)
spawn()
do_after_cooldown()
return max(0, inc_damage)
/*
/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/can_attach(obj/mecha/M as obj)
if(..())
if(!M.proc_res["dynattackby"])
@@ -27,10 +51,6 @@
..()
return
/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/get_equip_info()
if(!chassis) return
return "<span style=\"color:[equip_ready?"#0f0":"#f00"];\">*</span>&nbsp;[src.name]"
/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/proc/dynattackby(obj/item/weapon/W as obj, mob/user as mob)
if(!action_checks(user))
return chassis.dynattackby(W,user)
@@ -46,4 +66,5 @@
set_ready_state(0)
chassis.use_power(energy_drain)
do_after_cooldown()
return
return
*/
@@ -11,6 +11,45 @@
equip_type = EQUIP_HULL
/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/handle_projectile_contact(var/obj/item/projectile/Proj, var/inc_damage)
if(istype(Proj, /obj/item/projectile/test))
return inc_damage// Don't care about test projectiles, just what comes after them
if(!action_checks(src))
return inc_damage
if(prob(chassis.deflect_chance*deflect_coeff))
chassis.occupant_message("<span class='notice'>The armor deflects incoming projectile.</span>")
chassis.visible_message("The [chassis.name] armor deflects the projectile.")
chassis.log_append_to_last("Armor saved.")
inc_damage = 0
else
inc_damage *= src.damage_coeff
set_ready_state(0)
chassis.use_power(energy_drain)
spawn()
do_after_cooldown()
return max(0, inc_damage)
/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/handle_ranged_contact(var/obj/A, var/inc_damage = 0)
if(!action_checks(A))
return inc_damage
if(prob(chassis.deflect_chance*deflect_coeff))
chassis.occupant_message("<span class='notice'>The [A] bounces off the armor.</span>")
chassis.visible_message("The [A] bounces off \the [chassis]'s armor")
chassis.log_append_to_last("Armor saved.")
inc_damage = 0
else if(istype(A, /obj))
inc_damage *= damage_coeff
set_ready_state(0)
chassis.use_power(energy_drain)
spawn()
do_after_cooldown()
return max(0, inc_damage)
/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/get_equip_info()
if(!chassis) return
return "<span style=\"color:[equip_ready?"#0f0":"#f00"];\">*</span>&nbsp;[src.name]"
/*
/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/can_attach(obj/mecha/M as obj)
if(..())
if(!M.proc_res["dynbulletdamage"] && !M.proc_res["dynhitby"])
@@ -29,10 +68,6 @@
..()
return
/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/get_equip_info()
if(!chassis) return
return "<span style=\"color:[equip_ready?"#0f0":"#f00"];\">*</span>&nbsp;[src.name]"
/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/proc/dynbulletdamage(var/obj/item/projectile/Proj)
if(istype(Proj, /obj/item/projectile/test))
return // Don't care about test projectiles, just what comes after them
@@ -69,4 +104,5 @@
set_ready_state(0)
chassis.use_power(energy_drain)
do_after_cooldown()
return
return
*/
@@ -0,0 +1,34 @@
/*
* A special device used to pick up and equip other exosuit components on the fly, without leaving an Exosuit. Costly.
*/
/obj/item/mecha_parts/mecha_equipment/hardpoint_actuator
name = "hardpoint actuator clamp"
icon_state = "mecha_clamp"
equip_cooldown = 10 SECONDS
energy_drain = 600
equip_type = EQUIP_HULL
origin_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 5, TECH_POWER = 4, TECH_COMBAT = 1, TECH_MAGNET = 4)
/obj/item/mecha_parts/mecha_equipment/hardpoint_actuator/action(atom/target)
if(!action_checks(target))
return
if(istype(target,/obj/item/mecha_parts/mecha_equipment))
var/obj/item/mecha_parts/mecha_equipment/ME = target
if(ME.can_attach(chassis))
occupant_message("[ME] can be integrated. Stand by.")
if(do_after(chassis.occupant, 3 SECONDS, target))
if(ME.can_attach(chassis) && action_checks(target))
ME.attach(chassis)
occupant_message("[ME] successfully integrated.")
else
occupant_message("[ME] cannot be integrated due to lack of free hardpoints.")
else
occupant_message("[target] is not compatible with any present hardpoints.")
set_ready_state(0)
chassis.use_power(energy_drain)
do_after_cooldown()
return
@@ -0,0 +1,47 @@
/obj/item/mecha_parts/mecha_equipment/tool/powertool/inflatables
name = "inflatable deployment mechanism"
desc = "An exosuit-mounted inflatable barrier deployer. Useful!"
icon_state = "mecha_inflatables"
origin_tech = list(TECH_MATERIAL = 5, TECH_MAGNET = 3)
equip_cooldown = 3
energy_drain = 30
range = MELEE
equip_type = EQUIP_UTILITY
ready_sound = 'sound/effects/spray.ogg'
required_type = list(/obj/mecha/working/ripley)
tooltype = /obj/item/weapon/inflatable_dispenser/robot
var/obj/item/weapon/inflatable_dispenser/my_deployer = null
/obj/item/mecha_parts/mecha_equipment/tool/powertool/inflatables/Initialize()
..()
my_deployer = my_tool
/obj/item/mecha_parts/mecha_equipment/tool/powertool/inflatables/Topic(href, href_list)
..()
if(href_list["toggle_deployable_mode"])
my_deployer.attack_self()
update_chassis_page()
return
/obj/item/mecha_parts/mecha_equipment/tool/powertool/inflatables/get_equip_info()
if(!chassis) return
var/data_return = "<span style=\"color:[equip_ready?"#0f0":"#f00"];\">*</span>&nbsp;[chassis.selected==src?"<b>":"<a href='?src=\ref[chassis];select_equip=\ref[src]'>"][src.name][chassis.selected==src?"</b>":"</a>"] - <a href='?src=\ref[src];toggle_deployable_mode=1'>Deploy [my_deployer.mode?"Door":"Wall"]</a><br>\
&nbsp; - Doors left: <span style=\"color:#ff0;\">[my_deployer.stored_doors]</span>/[my_deployer.max_doors]<br>\
&nbsp; - Walls left: <span style=\"color:#ff0;\">[my_deployer.stored_walls]</span>/[my_deployer.max_walls]"
return data_return
/obj/item/mecha_parts/mecha_equipment/tool/powertool/inflatables/action(atom/target, params)
if(!action_checks(target))
return
if(istype(target, /turf))
my_deployer.try_deploy_inflatable(target, chassis.occupant)
if(istype(target, /obj/item/inflatable) || istype(target, /obj/structure/inflatable))
my_deployer.pick_up(target, chassis.occupant)
set_ready_state(0)
chassis.use_power(energy_drain)
do_after_cooldown()
return
+1 -1
View File
@@ -1,7 +1,7 @@
/obj/item/mecha_parts/mecha_equipment/tool/passenger
name = "passenger compartment"
desc = "A mountable passenger compartment for exosuits. Rather cramped."
icon_state = "mecha_abooster_ccw"
icon_state = "mecha_passenger"
origin_tech = list(TECH_ENGINEERING = 1, TECH_BIO = 1)
energy_drain = 10
range = MELEE
@@ -38,4 +38,18 @@
desc = "An exosuit-mounted pneumatic prybar."
icon_state = "mecha_crowbar"
tooltype = /obj/item/weapon/tool/crowbar/power
ready_sound = 'sound/mecha/gasdisconnected.ogg'
ready_sound = 'sound/mecha/gasdisconnected.ogg'
/obj/item/mecha_parts/mecha_equipment/tool/powertool/cutter
name = "pneumatic cablecutter"
desc = "An exosuit-mounted pneumatic cablecutter."
icon_state = "mecha_cablecutter"
tooltype = /obj/item/weapon/tool/wirecutters/power
ready_sound = 'sound/mecha/gasdisconnected.ogg'
/obj/item/mecha_parts/mecha_equipment/tool/powertool/screwdriver
name = "pneumatic screwdriver"
desc = "An exosuit-mounted pneumatic screwdriver."
icon_state = "mecha_screwdriver"
tooltype = /obj/item/weapon/tool/screwdriver/power
ready_sound = 'sound/mecha/gasdisconnected.ogg'
@@ -0,0 +1,34 @@
/obj/item/mecha_parts/mecha_equipment/tool/powertool/welding
name = "welding laser"
desc = "An exosuit-mounted welding laser."
icon_state = "mecha_laser-rig"
origin_tech = list(TECH_MATERIAL = 4, TECH_MAGNET = 3, TECH_POWER = 4, TECH_PHORON = 2)
equip_cooldown = 3
energy_drain = 15
range = MELEE
equip_type = EQUIP_UTILITY
ready_sound = 'sound/items/Ratchet.ogg'
required_type = list(/obj/mecha/working/ripley)
tooltype = /obj/item/weapon/weldingtool/electric/mounted/exosuit
/obj/item/mecha_parts/mecha_equipment/tool/powertool/welding/action(var/atom/target)
..()
var/datum/beam/weld_beam = null
if(is_ranged())
var/atom/movable/beam_origin = chassis
weld_beam = beam_origin.Beam(target, icon_state = "solar_beam", time = 0.3 SECONDS)
if(!do_after(chassis.occupant, 0.3 SECONDS, target))
qdel(weld_beam)
/obj/item/mecha_parts/mecha_equipment/tool/powertool/welding/attach(obj/mecha/M as obj)
..()
if(enable_special)
range = MELEE|RANGED
my_tool.reach = 7
else
range = MELEE
my_tool.reach = 1
@@ -15,6 +15,7 @@
equip_type = EQUIP_HULL
/*
/obj/item/mecha_parts/mecha_equipment/shocker/can_attach(obj/mecha/M as obj)
if(..())
if(!M.proc_res["dynattackby"] && !M.proc_res["dynattackhand"] && !M.proc_res["dynattackalien"])
@@ -25,9 +26,11 @@
..()
chassis.proc_res["dynattackby"] = src
return
*/
/obj/item/mecha_parts/mecha_equipment/shocker/proc/dynattackby(obj/item/weapon/W, mob/living/user)
/obj/item/mecha_parts/mecha_equipment/shocker/handle_melee_contact(var/obj/item/weapon/W, var/mob/living/user, var/inc_damage = null)
if(!action_checks(user) || !active)
return
user.electrocute_act(shock_damage, src)
return chassis.dynattackby(W,user)
return inc_damage
+17 -3
View File
@@ -622,7 +622,12 @@
else if(istype(A, /obj))
var/obj/O = A
if(O.throwforce)
src.take_damage(O.throwforce)
var/pass_damage = O.throwforce
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
pass_damage = ME.handle_ranged_contact(A, pass_damage)
src.take_damage(pass_damage)
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
return
@@ -652,7 +657,12 @@
var/ignore_threshold
if(istype(Proj, /obj/item/projectile/beam/pulse))
ignore_threshold = 1
src.take_damage(Proj.damage, Proj.check_armour)
var/pass_damage = Proj.damage
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
pass_damage = ME.handle_projectile_contact(Proj, pass_damage)
src.take_damage(pass_damage, Proj.check_armour)
if(prob(25)) spark_system.start()
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),ignore_threshold)
@@ -748,7 +758,11 @@
else
src.occupant_message("<font color='red'><b>[user] hits [src] with [W].</b></font>")
user.visible_message("<font color='red'><b>[user] hits [src] with [W].</b></font>", "<font color='red'><b>You hit [src] with [W].</b></font>")
src.take_damage(W.force,W.damtype)
var/pass_damage = W.force
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
pass_damage = ME.handle_projectile_contact(W, user, pass_damage)
src.take_damage(pass_damage,W.damtype)
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
return
+2 -6
View File
@@ -74,12 +74,8 @@
qdel(src)
/obj/effect/effect/foam/Crossed(var/atom/movable/AM)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = AM
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
if(AM.is_incorporeal())
return
if(metal)
return
if(istype(AM, /mob/living))
@@ -70,12 +70,8 @@ var/global/list/image/splatter_cache=list()
desc = initial(desc)
/obj/effect/decal/cleanable/blood/Crossed(mob/living/carbon/human/perp)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = perp
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
if(perp.is_incorporeal())
return
if (!istype(perp))
return
if(amount < 1)
+2 -6
View File
@@ -185,12 +185,8 @@ steam.start() -- spawns the effect
qdel(src)
/obj/effect/effect/smoke/Crossed(mob/living/carbon/M as mob )
//VOREStation Edit begin: SHADEKIN
var/mob/SK = M
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
if(M.is_incorporeal())
return
..()
if(istype(M))
affect(M)
@@ -6,4 +6,12 @@
light_range = 3
light_power = 1
light_color = "#FFFFFF"
/obj/effect/map_effect/perma_light/brighter
name = "permanent light (bright)"
icon_state = "permalight"
light_range = 5
light_power = 3
light_color = "#FFFFFF"
+3 -7
View File
@@ -35,13 +35,9 @@
explode()
..()
/obj/effect/mine/Crossed(AM as mob|obj)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = AM
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
/obj/effect/mine/Crossed(atom/movable/AM as mob|obj)
if(AM.is_incorporeal())
return
Bumped(AM)
/obj/effect/mine/Bumped(mob/M as mob|obj)
+3 -7
View File
@@ -20,13 +20,9 @@ GLOBAL_LIST_BOILERPLATE(all_portals, /obj/effect/portal)
return
return
/obj/effect/portal/Crossed(AM as mob|obj)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = AM
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
/obj/effect/portal/Crossed(atom/movable/AM as mob|obj)
if(AM.is_incorporeal())
return
if(istype(AM,/mob) && !(istype(AM,/mob/living)))
return //do not send ghosts, zshadows, ai eyes, etc
spawn(0)
+3 -7
View File
@@ -12,13 +12,9 @@
/obj/effect/step_trigger/proc/Trigger(var/atom/movable/A)
return 0
/obj/effect/step_trigger/Crossed(H as mob|obj)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = H
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
/obj/effect/step_trigger/Crossed(atom/movable/H as mob|obj)
if(H.is_incorporeal())
return
..()
if(!H)
return
+3 -7
View File
@@ -1468,13 +1468,9 @@ var/global/list/obj/item/device/pda/PDAs = list()
QDEL_NULL(src.pai)
return ..()
/obj/item/device/pda/clown/Crossed(AM as mob|obj) //Clown PDA is slippery.
//VOREStation Edit begin: SHADEKIN
var/mob/SK = AM
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
/obj/item/device/pda/clown/Crossed(atom/movable/AM as mob|obj) //Clown PDA is slippery.
if(AM.is_incorporeal())
return
if (istype(AM, /mob/living))
var/mob/living/M = AM
+1 -1
View File
@@ -425,7 +425,7 @@ var/list/civilian_cartridges = list(
if(mode==47)
var/supplyData[0]
var/datum/shuttle/ferry/supply/shuttle = supply_controller.shuttle
var/datum/shuttle/autodock/ferry/supply/shuttle = supply_controller.shuttle
if (shuttle)
supplyData["shuttle_moving"] = shuttle.has_arrive_time()
supplyData["shuttle_eta"] = shuttle.eta_minutes()
@@ -394,7 +394,7 @@
// code\game\machinery\computer\supply.dm, starting at line 55
/obj/item/weapon/commcard/proc/get_supply_shuttle_status()
var/shuttle_status[0]
var/datum/shuttle/ferry/supply/shuttle = supply_controller.shuttle
var/datum/shuttle/autodock/ferry/supply/shuttle = supply_controller.shuttle
if(shuttle)
if(shuttle.has_arrive_time())
shuttle_status["location"] = "In transit"
@@ -404,8 +404,8 @@
else
shuttle_status["time"] = 0
if(shuttle.at_station())
if(shuttle.docking_controller)
switch(shuttle.docking_controller.get_docking_status())
if(shuttle.shuttle_docking_controller)
switch(shuttle.shuttle_docking_controller.get_docking_status())
if("docked")
shuttle_status["location"] = "Docked"
shuttle_status["mode"] = SUP_SHUTTLE_DOCKED
+32 -18
View File
@@ -17,6 +17,32 @@ var/global/mob/living/carbon/human/dummy/mannequin/sleevemate_mob
var/datum/mind/stored_mind
var/ooc_notes = null //For holding prefs
//These don't perform any checks and need to be wrapped by checks
/obj/item/device/sleevemate/proc/clear_mind()
stored_mind = null
ooc_notes = null
update_icon()
/obj/item/device/sleevemate/proc/get_mind(mob/living/M)
ASSERT(M.mind)
ooc_notes = M.ooc_notes
stored_mind = M.mind
M.ghostize()
stored_mind.current = null
update_icon()
/obj/item/device/sleevemate/proc/put_mind(mob/living/M)
stored_mind.active = TRUE
stored_mind.transfer_to(M)
M.ooc_notes = ooc_notes
clear_mind()
/obj/item/device/sleevemate/attack(mob/living/M, mob/living/user)
if(ishuman(M))
scan_mob(M, user)
@@ -34,8 +60,7 @@ var/global/mob/living/carbon/human/dummy/mannequin/sleevemate_mob
switch(choice)
if("Delete")
to_chat(user,"<span class='notice'>Internal copy of [stored_mind.name] deleted.</span>")
stored_mind = null
update_icon()
clear_mind()
if("Backup")
to_chat(user,"<span class='notice'>Internal copy of [stored_mind.name] backed up to database.</span>")
SStranscore.m_backup(stored_mind,null,one_time = TRUE)
@@ -183,10 +208,7 @@ var/global/mob/living/carbon/human/dummy/mannequin/sleevemate_mob
usr.visible_message("<span class='warning'>[usr] begins downloading [target]'s mind!</span>","<span class='notice'>You begin downloading [target]'s mind!</span>")
if(do_after(usr,35 SECONDS,target)) //This is powerful, yo.
if(!stored_mind && target.mind)
stored_mind = target.mind
target.ghostize()
stored_mind.current = null
update_icon()
get_mind(target)
to_chat(usr,"<span class='notice'>Mind downloaded!</span>")
return
@@ -212,12 +234,9 @@ var/global/mob/living/carbon/human/dummy/mannequin/sleevemate_mob
if(!sleevemate_mob)
sleevemate_mob = new()
stored_mind.active = TRUE //Setting this causes transfer_to, to key them into the mob
stored_mind.transfer_to(sleevemate_mob)
put_mind(sleevemate_mob)
SC.catch_mob(sleevemate_mob)
stored_mind = null
to_chat(usr,"<span class='notice'>Mind transferred into Soulcatcher!</span>")
update_icon()
if(href_list["mindupload"])
if(!stored_mind)
@@ -238,11 +257,8 @@ var/global/mob/living/carbon/human/dummy/mannequin/sleevemate_mob
if(!stored_mind)
to_chat(usr,"<span class='warning'>\The [src] no longer has a stored mind.</span>")
return
stored_mind.active = TRUE
stored_mind.transfer_to(target)
stored_mind = null
put_mind(target)
to_chat(usr,"<span class='notice'>Mind transferred into [target]!</span>")
update_icon()
if(href_list["mindrelease"])
if(stored_mind)
@@ -254,10 +270,8 @@ var/global/mob/living/carbon/human/dummy/mannequin/sleevemate_mob
return
for(var/mob/living/carbon/brain/caught_soul/soul in SC.brainmobs)
if(soul.name == href_list["mindrelease"])
stored_mind = soul.mind
stored_mind.current = null
soul.Destroy()
update_icon()
get_mind(soul)
qdel(soul)
to_chat(usr,"<span class='notice'>Mind downloaded!</span>")
return
to_chat(usr,"<span class='notice'>Unable to find that mind in Soulcatcher!</span>")
@@ -16,6 +16,7 @@
var/abductor = 0 //Can be used on teleportation blocking turfs
var/list/beacons = list()
var/loc_network = null //Used if you want to create pre-made beacons on the maps
var/ready = 1
var/beacons_left = 3
var/failure_chance = 5 //Percent
@@ -24,8 +25,9 @@
var/list/warned_users = list()
var/list/logged_events = list()
/obj/item/device/perfect_tele/New()
..()
/obj/item/device/perfect_tele/Initialize()
. = ..()
flags |= NOBLUDGEON
if(cell_type)
power_source = new cell_type(src)
@@ -73,6 +75,12 @@
to_chat(user,"<span class='notice'>[src] does not have a power cell.</span>")
/obj/item/device/perfect_tele/attack_self(mob/user)
if(loc_network)
for(var/obj/item/device/perfect_tele_beacon/stationary/nb in premade_tele_beacons)
if(nb.tele_network == loc_network)
beacons[nb.tele_name] = nb
loc_network = null //Consumed
if(!(user.ckey in warned_users))
warned_users |= user.ckey
alert(user,"This device can be easily used to break ERP preferences due to the nature of teleporting \
@@ -380,6 +388,7 @@ GLOBAL_LIST_BOILERPLATE(premade_tele_beacons, /obj/item/device/perfect_tele_beac
/obj/item/device/perfect_tele/alien
name = "alien translocator"
desc = "This strange device allows one to teleport people and objects across large distances."
icon_state = "alientele"
cell_type = /obj/item/weapon/cell/device/weapon/recharge/alien
charge_cost = 400
@@ -388,13 +397,26 @@ GLOBAL_LIST_BOILERPLATE(premade_tele_beacons, /obj/item/device/perfect_tele_beac
longrange = 1
abductor = 1
/obj/item/device/perfect_tele/alien/bluefo
name = "hybrid translocator"
desc = "This strange device allows one to teleport people and objects across large distances. It has only a single preprogrammed destination, though."
icon_state = "alientele"
cell_type = /obj/item/weapon/cell/device/weapon/recharge/alien
charge_cost = 400
beacons_left = 0
failure_chance = 0
longrange = 1
abductor = 1
loc_network = "hybridshuttle"
/obj/item/device/perfect_tele/frontier
icon_state = "minitrans"
icon_state = "frontiertrans"
beacons_left = 1 //Just one
battery_lock = 1
unacidable = 1
failure_chance = 0 //Percent
var/loc_network = null
var/phase_power = 75
var/recharging = 0
@@ -429,12 +451,6 @@ GLOBAL_LIST_BOILERPLATE(premade_tele_beacons, /obj/item/device/perfect_tele_beac
loc_network = "centcom"
longrange = 1
/obj/item/device/perfect_tele/frontier/staff/New()
..()
for(var/obj/item/device/perfect_tele_beacon/stationary/nb in premade_tele_beacons)
if(nb.tele_network == loc_network)
beacons[nb.tele_name] = nb
/obj/item/device/perfect_tele/frontier/unknown
name = "modified translocator"
desc = "This crank-charged translocator has only one beacon, but it already has a destination preprogrammed into it."
@@ -442,12 +458,6 @@ GLOBAL_LIST_BOILERPLATE(premade_tele_beacons, /obj/item/device/perfect_tele_beac
longrange = 1
abductor = 1
/obj/item/device/perfect_tele/frontier/unknown/New()
..()
for(var/obj/item/device/perfect_tele_beacon/stationary/nb in premade_tele_beacons)
if(nb.tele_network == loc_network)
beacons[nb.tele_name] = nb
/obj/item/device/perfect_tele/frontier/unknown/one
loc_network = "unkone"
/obj/item/device/perfect_tele/frontier/unknown/two
+3 -7
View File
@@ -355,13 +355,9 @@
playsound(src, 'sound/effects/snap.ogg', 50, 1)
qdel(src)
/obj/item/toy/snappop/Crossed(H as mob|obj)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = H
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
/obj/item/toy/snappop/Crossed(atom/movable/H as mob|obj)
if(H.is_incorporeal())
return
if((ishuman(H))) //i guess carp and shit shouldn't set them off
var/mob/living/carbon/M = H
if(M.m_intent == "run")
+6 -14
View File
@@ -8,13 +8,9 @@
/*
* Banana Peals
*/
/obj/item/weapon/bananapeel/Crossed(AM as mob|obj)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = AM
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
/obj/item/weapon/bananapeel/Crossed(atom/movable/AM as mob|obj)
if(AM.is_incorporeal())
return
if (istype(AM, /mob/living))
var/mob/living/M = AM
M.slip("the [src.name]",4)
@@ -29,13 +25,9 @@
/obj/item/weapon/soap/proc/wet()
reagents.add_reagent("cleaner", 5)
/obj/item/weapon/soap/Crossed(AM as mob|obj)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = AM
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
/obj/item/weapon/soap/Crossed(atom/movable/AM as mob|obj)
if(AM.is_incorporeal())
return
if (istype(AM, /mob/living))
var/mob/living/M = AM
M.slip("the [src.name]",3)
@@ -106,14 +106,10 @@
qdel(src)
return
/obj/item/weapon/material/shard/Crossed(AM as mob|obj)
/obj/item/weapon/material/shard/Crossed(atom/movable/AM as mob|obj)
..()
//VOREStation Edit begin: SHADEKIN
var/mob/SK = AM
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
if(AM.is_incorporeal())
return
if(isliving(AM))
var/mob/M = AM
@@ -644,6 +644,10 @@
var/obj/item/weapon/rig/suit = H.back
if(istype(suit))
return suit.cell
if(istype(src.loc, /obj/item/mecha_parts/mecha_equipment))
var/obj/item/mecha_parts/mecha_equipment/mounting = src.loc
if(mounting.chassis && mounting.chassis.cell)
return mounting.chassis.cell
return null
/obj/item/weapon/weldingtool/electric/mounted
@@ -652,4 +656,26 @@
/obj/item/weapon/weldingtool/electric/mounted/cyborg
toolspeed = 0.5
#undef WELDER_FUEL_BURN_INTERVAL
/obj/item/weapon/weldingtool/electric/mounted/exosuit
var/obj/item/mecha_parts/mecha_equipment/equip_mount = null
flame_intensity = 1
eye_safety_modifier = 2
always_process = TRUE
/obj/item/weapon/weldingtool/electric/mounted/exosuit/Initialize()
..()
if(istype(loc, /obj/item/mecha_parts/mecha_equipment))
equip_mount = loc
/obj/item/weapon/weldingtool/electric/mounted/exosuit/process()
..()
if(equip_mount && equip_mount.chassis)
var/obj/mecha/M = equip_mount.chassis
if(M.selected == equip_mount && get_fuel())
setWelding(TRUE, M.occupant)
else
setWelding(FALSE, M.occupant)
#undef WELDER_FUEL_BURN_INTERVAL
+3 -7
View File
@@ -107,13 +107,9 @@
deployed = 0
can_buckle = initial(can_buckle)
/obj/item/weapon/beartrap/Crossed(AM as mob|obj)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = AM
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
/obj/item/weapon/beartrap/Crossed(atom/movable/AM as mob|obj)
if(AM.is_incorporeal())
return
if(deployed && isliving(AM))
var/mob/living/L = AM
if(L.m_intent == "run")
+1 -7
View File
@@ -87,14 +87,8 @@
return ..()
/obj/structure/catwalk/Crossed()
//VOREStation Edit begin: SHADEKIN
var/mob/SK = usr
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
. = ..()
if(isliving(usr))
if(isliving(usr) && !usr.is_incorporeal())
playsound(src, pick('sound/effects/footstep/catwalk1.ogg', 'sound/effects/footstep/catwalk2.ogg', 'sound/effects/footstep/catwalk3.ogg', 'sound/effects/footstep/catwalk4.ogg', 'sound/effects/footstep/catwalk5.ogg'), 25, 1)
/obj/structure/catwalk/CheckExit(atom/movable/O, turf/target)
@@ -19,6 +19,8 @@
var/list/spawnitems = list(/obj/item/weapon/tank/emergency/oxygen,/obj/item/clothing/mask/breath,/obj/item/weapon/tool/crowbar/red)
var/amount = 2 // spawns each items X times.
icon_state = "emerg"
icon_closed = "emerg"
icon_opened = "emerg_open"
/obj/structure/closet/walllocker/emerglocker/toggle(mob/user as mob)
src.attack_hand(user)
@@ -0,0 +1,13 @@
/obj/structure/prop/alien/computer/hybrid
name = "hybrid console"
desc = "The console flashes what appear to be symbols you've never seen before, intermixed with human writing moving too fast to comprehend."
icon = 'icons/obj/abductor_vr.dmi'
icon_state = "console-c"
interaction_message = "<span class='warning'>The screen flashes an 'access denied' message at you. Perhaps for the best.</span>"
/obj/structure/prop/alien/pod/hybrid
name = "hybrid pod"
desc = "This seems to be a container for something."
icon = 'icons/obj/abductor_vr.dmi'
icon_state = "experiment"
interaction_message = "<span class='warning'>You don't see any mechanism to open this thing. Probably for the best.</span>"
@@ -0,0 +1,23 @@
/material/flockium
name = "flockium"
//stack_type = /obj/item/stack/material/sandstone
icon_base = "flock"
icon_reinf = "flock"
icon_colour = "#FFFFFF"
//shard_type = SHARD_STONE_PIECE
weight = 30
hardness = 200
protectiveness = 5 // 20%
conductive = 0
conductivity = 0
door_icon_base = "flockdoor"
sheet_singular_name = "quanta"
sheet_plural_name = "quanta"
/obj/structure/simple_door/flock
name = "aperture"
icon = 'icons/goonstation/featherzone.dmi'
icon_state = "flockdoor"
/obj/structure/simple_door/flock/New(var/newloc, var/newmat)
..(newloc, "flockium")
@@ -42,7 +42,7 @@
/obj/structure/bed/update_icon()
// Prep icon.
icon_state = ""
overlays.Cut()
cut_overlays()
// Base icon.
var/cache_key = "[base_icon]-[material.name]"
if(isnull(stool_cache[cache_key]))
@@ -50,7 +50,7 @@
if(applies_material_colour) //VOREStation Add - Goes with added var
I.color = material.icon_colour
stool_cache[cache_key] = I
overlays |= stool_cache[cache_key]
add_overlay(stool_cache[cache_key])
// Padding overlay.
if(padding_material)
var/padding_cache_key = "[base_icon]-padding-[padding_material.name]"
@@ -58,7 +58,7 @@
var/image/I = image(icon, "[base_icon]_padding")
I.color = padding_material.icon_colour
stool_cache[padding_cache_key] = I
overlays |= stool_cache[padding_cache_key]
add_overlay(stool_cache[padding_cache_key])
// Strings.
desc = initial(desc)
if(padding_material)
@@ -47,13 +47,12 @@
var/cache_key = "[base_icon]-armrest-[padding_material ? padding_material.name : "no_material"]"
if(isnull(stool_cache[cache_key]))
var/image/I = image(icon, "[base_icon]_armrest")
I.layer = MOB_LAYER + 0.1
I.plane = MOB_PLANE
I.layer = ABOVE_MOB_LAYER
if(padding_material)
I.color = padding_material.icon_colour
stool_cache[cache_key] = I
overlays |= stool_cache[cache_key]
stool_cache[cache_key] = I
add_overlay(stool_cache[cache_key])
/obj/structure/bed/chair/proc/update_layer()
if(src.dir == NORTH)
@@ -11,7 +11,7 @@
var/image/I = image(icon, "[base_icon]_over")
I.layer = ABOVE_MOB_LAYER
I.plane = MOB_PLANE
overlays |= I
add_overlay(I)
/obj/structure/bed/chair/bar_stool
name = "bar stool"
@@ -37,14 +37,14 @@ var/global/list/stool_cache = list() //haha stool
/obj/item/weapon/stool/update_icon()
// Prep icon.
icon_state = ""
overlays.Cut()
cut_overlays()
// Base icon.
var/cache_key = "stool-[material.name]"
if(isnull(stool_cache[cache_key]))
var/image/I = image(icon, base_icon)
I.color = material.icon_colour
stool_cache[cache_key] = I
overlays |= stool_cache[cache_key]
add_overlay(stool_cache[cache_key])
// Padding overlay.
if(padding_material)
var/padding_cache_key = "stool-padding-[padding_material.name]"
@@ -52,7 +52,7 @@ var/global/list/stool_cache = list() //haha stool
var/image/I = image(icon, "[base_icon]_padding") //VOREStation Edit
I.color = padding_material.icon_colour
stool_cache[padding_cache_key] = I
overlays |= stool_cache[padding_cache_key]
add_overlay(stool_cache[padding_cache_key])
// Strings.
if(padding_material)
name = "[padding_material.display_name] [initial(name)]" //this is not perfect but it will do for now.
@@ -14,9 +14,9 @@
/obj/structure/bed/chair/wheelchair/set_dir()
..()
overlays = null
cut_overlays()
var/image/O = image(icon = 'icons/obj/furniture.dmi', icon_state = "w_overlay", layer = FLY_LAYER, dir = src.dir)
overlays += O
add_overlay(O)
if(has_buckled_mobs())
for(var/A in buckled_mobs)
var/mob/living/L = A
+2 -2
View File
@@ -55,7 +55,7 @@
return new_dest
/obj/landed_holder/proc/leave_turf()
/obj/landed_holder/proc/leave_turf(var/turf/base_turf = null)
var/turf/new_source
//Change our source to whatever it was before
if(turf_type)
@@ -67,7 +67,7 @@
new_source.underlays = underlays
new_source.decals = decals
else
new_source = my_turf.ChangeTurf(get_base_turf_by_area(my_turf),,1)
new_source = my_turf.ChangeTurf(base_turf ? base_turf : get_base_turf_by_area(my_turf),,1)
return new_source
+28 -1
View File
@@ -1,3 +1,17 @@
/turf/simulated/shuttle/floor/alienplating/blue
icon = 'icons/turf/shuttle_alien_blue.dmi'
icon_state = "alienplating"
/turf/simulated/shuttle/floor/alienplating/blue/half
icon_state = "alienplatinghalf"
/turf/simulated/shuttle/floor/alien/blue
icon = 'icons/turf/shuttle_alien_blue.dmi'
icon_state = "alienpod1"
light_range = 4
light_power = 0.8
light_color = "#66ffff" // Bright cyan.
/turf/simulated/floor/flesh
name = "flesh"
desc = "This slick flesh ripples and squishes under your touch"
@@ -14,4 +28,17 @@
return
/turf/simulated/floor/flesh/ex_act(severity)
return
return
/turf/simulated/floor/flock
icon = 'icons/goonstation/featherzone.dmi'
icon_state = "floor"
/turf/simulated/floor/flock/Crossed(var/atom/movable/AM)
. = ..()
if(isliving(AM))
icon_state = "floor-on"
set_light(3,3,"#26c5a9")
spawn(5 SECONDS)
icon_state = "floor"
set_light(0,0,"#ffffff")
+12 -1
View File
@@ -59,4 +59,15 @@ var/list/flesh_overlay_cache = list()
for(var/direction in alldirs)
if(istype(get_step(src, direction), /turf/simulated/flesh))
var/turf/simulated/flesh/F = get_step(src, direction)
F.update_icon()
F.update_icon()
/turf/simulated/shuttle/wall/flock
icon = 'icons/goonstation/featherzone.dmi'
icon_state = "flockwall0"
base_state = "flockwall"
hard_corner = 1 //They're all HC
true_name = "wall"
/turf/simulated/shuttle/wall/flock/Initialize()
. = ..()
set_light(3,3,"#26c5a9")
+17
View File
@@ -16,6 +16,8 @@
var/depth = 1 // Higher numbers indicates deeper water.
var/reagent_type = "water"
/turf/simulated/floor/water/Initialize()
. = ..()
update_icon()
@@ -33,6 +35,21 @@
/turf/simulated/floor/water/get_edge_icon_state()
return "water_shallow"
/turf/simulated/floor/water/attackby(obj/item/O as obj, mob/user as mob)
var/obj/item/weapon/reagent_containers/RG = O
if (istype(RG) && RG.is_open_container())
RG.reagents.add_reagent(reagent_type, min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this))
user.visible_message("<span class='notice'>[user] fills \the [RG] using \the [src].</span>","<span class='notice'>You fill \the [RG] using \the [src].</span>")
return 1
else if(istype(O, /obj/item/weapon/mop))
O.reagents.add_reagent(reagent_type, 5)
to_chat(user, "<span class='notice'>You wet \the [O] in \the [src].</span>")
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
return 1
else return ..()
/turf/simulated/floor/water/return_air_for_internal_lifeform(var/mob/living/L)
if(L && L.lying)
if(L.can_breathe_water()) // For squid.
+3
View File
@@ -24,6 +24,9 @@
for(var/obj/O in src)
O.hide(0)
/turf/space/is_solid_structure()
return locate(/obj/structure/lattice, src) //counts as solid structure if it has a lattice
/turf/space/proc/update_starlight()
if(!config.starlight)
return
+4
View File
@@ -64,6 +64,10 @@
/turf/proc/is_intact()
return 0
// Used by shuttle code to check if this turf is empty enough to not crush want it lands on.
/turf/proc/is_solid_structure()
return 1
/turf/attack_hand(mob/user)
if(!(user.canmove) || user.restrained() || !(user.pulling))
return 0
@@ -2,17 +2,17 @@
name = "Jump a Shuttle"
/datum/admin_secret_item/admin_secret/jump_shuttle/can_execute(var/mob/user)
if(!shuttle_controller) return 0
if(!SSshuttles) return 0
return ..()
/datum/admin_secret_item/admin_secret/jump_shuttle/execute(var/mob/user)
. = ..()
if(!.)
return
var/shuttle_tag = input(user, "Which shuttle do you want to jump?") as null|anything in shuttle_controller.shuttles
var/shuttle_tag = input(user, "Which shuttle do you want to jump?") as null|anything in SSshuttles.shuttles
if (!shuttle_tag) return
var/datum/shuttle/S = shuttle_controller.shuttles[shuttle_tag]
var/datum/shuttle/S = SSshuttles.shuttles[shuttle_tag]
var/origin_area = input(user, "Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world
if (!origin_area) return
@@ -2,7 +2,7 @@
name = "Launch a Shuttle"
/datum/admin_secret_item/admin_secret/launch_shuttle/can_execute(var/mob/user)
if(!shuttle_controller) return 0
if(!SSshuttles) return 0
return ..()
/datum/admin_secret_item/admin_secret/launch_shuttle/execute(var/mob/user)
@@ -10,15 +10,15 @@
if(!.)
return
var/list/valid_shuttles = list()
for (var/shuttle_tag in shuttle_controller.shuttles)
if (istype(shuttle_controller.shuttles[shuttle_tag], /datum/shuttle/ferry))
for (var/shuttle_tag in SSshuttles.shuttles)
if (istype(SSshuttles.shuttles[shuttle_tag], /datum/shuttle/autodock))
valid_shuttles += shuttle_tag
var/shuttle_tag = input(user, "Which shuttle do you want to launch?") as null|anything in valid_shuttles
if (!shuttle_tag)
return
var/datum/shuttle/ferry/S = shuttle_controller.shuttles[shuttle_tag]
var/datum/shuttle/autodock/S = SSshuttles.shuttles[shuttle_tag]
if (S.can_launch())
S.launch(user)
log_and_message_admins("launched the [shuttle_tag] shuttle", user)
@@ -2,7 +2,7 @@
name = "Launch a Shuttle (Forced)"
/datum/admin_secret_item/admin_secret/launch_shuttle_forced/can_execute(var/mob/user)
if(!shuttle_controller) return 0
if(!SSshuttles) return 0
return ..()
/datum/admin_secret_item/admin_secret/launch_shuttle_forced/execute(var/mob/user)
@@ -10,15 +10,15 @@
if(!.)
return
var/list/valid_shuttles = list()
for (var/shuttle_tag in shuttle_controller.shuttles)
if (istype(shuttle_controller.shuttles[shuttle_tag], /datum/shuttle/ferry))
for (var/shuttle_tag in SSshuttles.shuttles)
if (istype(SSshuttles.shuttles[shuttle_tag], /datum/shuttle/autodock))
valid_shuttles += shuttle_tag
var/shuttle_tag = input(user, "Which shuttle's launch do you want to force?") as null|anything in valid_shuttles
if (!shuttle_tag)
return
var/datum/shuttle/ferry/S = shuttle_controller.shuttles[shuttle_tag]
var/datum/shuttle/autodock/S = SSshuttles.shuttles[shuttle_tag]
if (S.can_force())
S.force_launch(user)
log_and_message_admins("forced the [shuttle_tag] shuttle", user)
@@ -2,7 +2,7 @@
name = "Move a Shuttle"
/datum/admin_secret_item/admin_secret/move_shuttle/can_execute(var/mob/user)
if(!shuttle_controller) return 0
if(!SSshuttles) return 0
return ..()
/datum/admin_secret_item/admin_secret/move_shuttle/execute(var/mob/user)
@@ -13,16 +13,15 @@
if (confirm == "Cancel")
return
var/shuttle_tag = input(user, "Which shuttle do you want to jump?") as null|anything in shuttle_controller.shuttles
var/shuttle_tag = input(user, "Which shuttle do you want to jump?") as null|anything in SSshuttles.shuttles
if (!shuttle_tag) return
var/datum/shuttle/S = shuttle_controller.shuttles[shuttle_tag]
var/datum/shuttle/S = SSshuttles.shuttles[shuttle_tag]
var/origin_area = input(user, "Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world
if (!origin_area) return
var/destination_tag = input(user, "Which landmark do you want to jump to? (IF YOU GET THIS WRONG THINGS WILL BREAK)") as null|anything in SSshuttles.registered_shuttle_landmarks
if (!destination_tag) return
var/destination_location = SSshuttles.get_landmark(destination_tag)
if (!destination_location) return
var/destination_area = input(user, "Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world
if (!destination_area) return
S.move(origin_area, destination_area)
S.attempt_move(destination_location)
log_and_message_admins("moved the [shuttle_tag] shuttle", user)
-4
View File
@@ -103,15 +103,11 @@
// 'Tactical' processes such as moving a step, meleeing an enemy, firing a projectile, and other fairly cheap actions that need to happen quickly.
/datum/ai_holder/proc/handle_tactics()
if(busy)
return
handle_special_tactic()
handle_stance_tactical()
// 'Strategical' processes that are more expensive on the CPU and so don't get run as often as the above proc, such as A* pathfinding or robust targeting.
/datum/ai_holder/proc/handle_strategicals()
if(busy)
return
handle_special_strategical()
handle_stance_strategical()
+2 -6
View File
@@ -104,12 +104,8 @@
/obj/item/device/assembly_holder/Crossed(atom/movable/AM as mob|obj)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = AM
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
if(AM.is_incorporeal())
return
if(a_left)
a_left.Crossed(AM)
if(a_right)
+2 -6
View File
@@ -242,12 +242,8 @@
return
/obj/effect/beam/i_beam/Crossed(atom/movable/AM as mob|obj)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = AM
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
if(AM.is_incorporeal())
return
if(istype(AM, /obj/effect/beam))
return
spawn(0)
+3 -7
View File
@@ -82,13 +82,9 @@
..()
/obj/item/device/assembly/mousetrap/Crossed(AM as mob|obj)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = AM
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
/obj/item/device/assembly/mousetrap/Crossed(atom/movable/AM as mob|obj)
if(AM.is_incorporeal())
return
if(armed)
if(ishuman(AM))
var/mob/living/carbon/H = AM
+1
View File
@@ -428,6 +428,7 @@ client/verb/character_setup()
//Log, disable
log_debug("[key_name(src)] reloaded VChat.")
winset(src, null, "outputwindow.htmloutput.is-visible=false;outputwindow.oldoutput.is-visible=false;outputwindow.chatloadlabel.is-visible=true")
//The hard way
qdel_null(src.chatOutput)
+46 -2
View File
@@ -526,6 +526,25 @@
src.name = "Frosted Jelly Donut"
reagents.add_reagent("sprinkles", 2)
/obj/item/weapon/reagent_containers/food/snacks/donut/poisonberry
name = "Jelly Donut"
desc = "You jelly?"
icon_state = "jdonut1"
filling_color = "#ED1169"
center_of_mass = list("x"=16, "y"=11)
nutriment_amt = 3
/obj/item/weapon/reagent_containers/food/snacks/donut/poisonberry/Initialize()
. = ..()
reagents.add_reagent("sprinkles", 1)
reagents.add_reagent("poisonberryjuice", 5)
bitesize = 5
if(prob(30))
src.icon_state = "jdonut2"
src.overlay_state = "box-donut2"
src.name = "Frosted Jelly Donut"
reagents.add_reagent("sprinkles", 2)
/obj/item/weapon/reagent_containers/food/snacks/donut/slimejelly
name = "Jelly Donut"
desc = "You jelly?"
@@ -1121,9 +1140,16 @@
/obj/item/weapon/reagent_containers/food/snacks/berryclafoutis/Initialize()
. = ..()
reagents.add_reagent("berryjuice", 5)
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/berryclafoutis/berry/Initialize()
. = ..()
reagents.add_reagent("berryjuice", 5)
/obj/item/weapon/reagent_containers/food/snacks/berryclafoutis/poison/Initialize()
. = ..()
reagents.add_reagent("poisonberryjuice", 5)
/obj/item/weapon/reagent_containers/food/snacks/waffles
name = "waffles"
desc = "Mmm, waffles"
@@ -3904,13 +3930,21 @@
filling_color = "#E0CF9B"
center_of_mass = list("x"=17, "y"=4)
nutriment_amt = 6
nutriment_desc = list("sweetness" = 2, "muffin" = 2, "berries" = 2)
nutriment_desc = list("sweetness" = 2, "muffin" = 2)
/obj/item/weapon/reagent_containers/food/snacks/berrymuffin/Initialize()
. = ..()
reagents.add_reagent("nutriment", 6)
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/berrymuffin/berry/Initialize()
. = ..()
reagents.add_reagent("berryjuice", 3)
/obj/item/weapon/reagent_containers/food/snacks/berrymuffin/poison/Initialize()
. = ..()
reagents.add_reagent("poisonberryjuice", 3)
/obj/item/weapon/reagent_containers/food/snacks/ghostmuffin
name = "booberry muffin"
desc = "My stomach is a graveyard! No living being can quench my bloodthirst!"
@@ -3925,6 +3959,16 @@
reagents.add_reagent("nutriment", 6)
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/ghostmuffin/berry/Initialize()
. = ..()
reagents.add_reagent("berryjuice", 3)
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/ghostmuffin/poison/Initialize()
. = ..()
reagents.add_reagent("poisonberryjuice", 3)
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/eggroll
name = "egg roll"
desc = "Free with orders over 10 thalers."
+279 -280
View File
@@ -1,280 +1,279 @@
// Chaos cake
/datum/recipe/microwave/chaoscake_layerone
reagents = list("flour" = 300,"milk" = 200, "sugar" = 100, "egg" = 30)
fruit = list("poisonberries" = 15, "cherries" = 15)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/meat/,
/obj/item/weapon/reagent_containers/food/snacks/meat/,
/obj/item/weapon/reagent_containers/food/snacks/meat/,
/obj/item/weapon/reagent_containers/food/snacks/meat/
)
result = /obj/structure/chaoscake
/datum/recipe/microwave/chaoscake_layertwo
reagents = list("flour" = 300, "milk" = 200, "sugar" = 100, "egg" = 30, )
fruit = list("vanilla" = 15, "banana" = 15)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough
)
result = /obj/item/weapon/chaoscake_layer
/datum/recipe/microwave/chaoscake_layerthree
reagents = list("flour" = 240, "milk" = 150, "sugar" = 80, "egg" = 24, "deathbell" = 100)
fruit = list("grapes" = 30)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough
)
result = /obj/item/weapon/chaoscake_layer/three
/datum/recipe/microwave/chaoscake_layerfour
reagents = list("flour" = 240, "milk" = 150, "sugar" = 80, "egg" = 24, "milkshake" = 300)
fruit = list("rice" = 30)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough
)
result = /obj/item/weapon/chaoscake_layer/four
/datum/recipe/microwave/chaoscake_layerfive
reagents = list("flour" = 180, "milk" = 100, "sugar" = 60, "egg" = 18, "blood" = 300)
fruit = list("tomato" = 20)
items = list() //supposed to be made with lobster, still has to be ported.
result = /obj/item/weapon/chaoscake_layer/five
/datum/recipe/microwave/chaoscake_layersix
reagents = list("flour" = 180, "milk" = 100, "sugar" = 60, "egg" = 18, "sprinkles" = 10)
fruit = list("apple" = 30)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/chocolatebar,
/obj/item/weapon/reagent_containers/food/snacks/chocolatebar,
/obj/item/weapon/reagent_containers/food/snacks/chocolatebar
)
result = /obj/item/weapon/chaoscake_layer/six
/datum/recipe/microwave/chaoscake_layerseven
reagents = list("flour" = 120, "milk" = 50, "sugar" = 40, "egg" = 12, "devilskiss" = 200)
fruit = list("potato" = 10)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough
)
result = /obj/item/weapon/chaoscake_layer/seven
/datum/recipe/microwave/chaoscake_layereight
reagents = list("flour" = 120, "milk" = 50, "sugar" = 40, "egg" = 12, "cream" = 200)
fruit = list("lemon" = 10)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough
)
result = /obj/item/weapon/chaoscake_layer/eight
/datum/recipe/microwave/chaoscake_layernine
reagents = list("water" = 100, "blood" = 100)
fruit = list("goldapple" = 50)
items = list()
result = /obj/item/weapon/chaoscake_layer/nine
/obj/structure/chaoscake
name = "An unfinished cake"
desc = "A single layer of a strange cake, you can see the cherry paste ooze, but it feels very incomplete..."
icon = 'icons/obj/food64x64.dmi'
icon_state = "chaoscake_unfinished-1"
pixel_x = -16
var/slices = 6
var/maxslices = 6
var/stage = 1
var/maxstages = 9
var/edible = 0
var/regentime = 1000
var/interval = 0
var/static/list/desclist2 = list(
"The first layer of a strange cake, you can see the cherry paste ooze.",
"The second layer of the cake sits in place now, smelling of pear with delicious colourful cream.",
"The third layer of cake adds a strange purple layer, glazed over with frosting. It smells of grapes, but with a hint of something foul underneath.",
"With the fourth layer added the cake looks happier again. Reeking of vanilla, it brings up memories of childhood joy.",
"The fifth layer is extremely disturbing on that cake. Smelling of pure copper, it seems that bright blood clots are forming on top.",
"The cake is getting closer with the sixth layer added, the pink hue smelling of chocolate, with colourful sprinkles on top.",
"The first pair of triplets rest on the cake, despite being mostly similar to the first three, an evil aura becomes noticable.",
"The second pair of triplets rest on the cake, if you stand on the bright side, you can feel a good aura lifting your mood.",
"A chaos cake. Both a creation of dark and light, the two cakes are kept in a careful balance by that mystical coin in the middle. It's said its effects would dissipate if the balance is ever tipped in favour of one side too much, so both sides much be cut equally."
)
/obj/item/weapon/chaoscake_layer
name = "A layer of cake"
desc = "a layer of cake, it is made out of colourful cream."
icon = 'icons/obj/food.dmi'
icon_state = "chaoscake_layer-2"
var/layer_stage = 1
/obj/item/weapon/chaoscake_layer/three
desc = "a layer of cake, glazed in purple."
icon_state = "chaoscake_layer-3"
layer_stage = 2
/obj/item/weapon/chaoscake_layer/four
desc = "a layer of cake, reminding you of a colouring book."
icon_state = "chaoscake_layer-4"
layer_stage = 3
/obj/item/weapon/chaoscake_layer/five
desc = "A layer of cake, smells like copper."
icon_state = "chaoscake_layer-5"
layer_stage = 4
/obj/item/weapon/chaoscake_layer/six
desc = "A layer of cake, featuring colourful sprinkles."
icon_state = "chaoscake_layer-6"
layer_stage = 5
/obj/item/weapon/chaoscake_layer/seven
desc = "A triplet of evil cake parts."
icon_state = "chaoscake_layer-7"
layer_stage = 6
/obj/item/weapon/chaoscake_layer/eight
desc = "A triplet of good cake parts."
icon_state = "chaoscake_layer-8"
layer_stage = 7
/obj/item/weapon/chaoscake_layer/nine
name = "A coin of balance"
desc = "A very peculiar coin, it seems to stabilise the air around it."
icon_state = "chaoscake_layer-9"
layer_stage = 8
/obj/structure/chaoscake/proc/HasSliceMissing()
..()
if(slices < maxslices)
if(interval >= regentime)
interval = 0
slices++
HasSliceMissing()
else
interval++
HasSliceMissing()
else
return
/obj/item/weapon/reagent_containers/food/snacks/chaoscakeslice
name = "The Chaos Cake Slice"
desc = "A slice from The Chaos Cake, it pulses weirdly, as if angry to be seperated from the whole"
icon_state = "chaoscake_slice-1"
center_of_mass = list("x"=16, "y"=10)
nutriment_desc = list()
nutriment_amt = 4
volume = 80
/obj/item/weapon/reagent_containers/food/snacks/chaoscakeslice/Initialize()
..()
var/i = rand(1,6)
icon_state = "chaoscake_slice-[i]"
switch(i)
if(1)
name = "Slice Of Evil" //Pretty damn poisonous, takes a lot of work to make safe for consumption, useful for medical.
desc = "An odd slice, despite the grease and cherries oozing off the top, it smells delicious."
nutriment_desc = list("The desire to consume" = 10) // You won't even taste the poison.
reagents.add_reagent("neurotoxic_protein", 2)
reagents.add_reagent("shockchem", 2)
reagents.add_reagent("amatoxin", 2)
reagents.add_reagent("carpotoxin", 2)
reagents.add_reagent("spidertoxin", 2)
bitesize = 7
if(2)
name = "Slice Of Evil" //A bad trip
desc = "A mysterious slice, coated in purple frosting that smells like grapes."
nutriment_desc = list("The desire to show off an party" = 10)
reagents.add_reagent("stoxin", 2)
reagents.add_reagent("space_drugs", 10)
reagents.add_reagent("serotrotium", 4)
reagents.add_reagent("cryptobiolin", 8)
reagents.add_reagent("mindbreaker", 10)
reagents.add_reagent("psilocybin", 10)
bitesize = 30 //even a single bite won't make you escape fate.
if(3)
name = "Slice Of Evil" //acidic
desc = "A menacing slice, smelling clearly of copper, blood clots float on top."
nutriment_desc = list("Infernal Rage" = 10)
reagents.add_reagent("blood", 20)
reagents.add_reagent("stomacid", 10)
reagents.add_reagent("mutagen", 4)
reagents.add_reagent("thirteenloko", 20)
reagents.add_reagent("hyperzine", 10)
bitesize = 30
if(4)
name = "Slice Of Good" //anti-tox
desc = "A colourful slice, smelling of pear and coated in delicious cream."
nutriment_desc = list("Hapiness" = 10)
reagents.add_reagent("anti_toxin", 2)
reagents.add_reagent("tricordrazine", 2)
bitesize = 3
if(5)
name = "Slice Of Good" //anti-oxy
desc = "A light slice, it's pretty to look at and smells of vanilla."
nutriment_desc = list("Freedom" = 10)
reagents.add_reagent("dexalinp", 2)
reagents.add_reagent("tricordrazine", 2)
bitesize = 3
if(6)
name = "Slice Of Good" //anti-burn/brute
desc = "A hearty slice, it smells of chocolate and strawberries."
nutriment_desc = list("Love" = 10)
reagents.add_reagent("bicaridine", 2)
reagents.add_reagent("tricordrazine", 2)
reagents.add_reagent("kelotane", 2)
bitesize = 4
/obj/structure/chaoscake/attackby(var/obj/item/weapon/W, var/mob/living/user)
if(istype(W,/obj/item/weapon/material/knife))
if(edible == 1)
HasSliceMissing()
if(slices <= 0)
to_chat(user, "The cake hums away quietly as the chaos powered goodness slowly recovers the large amount of lost mass, best to give it a moment before cutting another slice.")
return
else
to_chat(user, "You cut a slice of the cake. The slice looks like the cake was just baked, and you can see before your eyes as the spot where you cut the slice slowly regenerates!")
slices = slices - 1
icon_state = "chaoscake-[slices]"
new /obj/item/weapon/reagent_containers/food/snacks/chaoscakeslice(src.loc)
else
to_chat(user, "<span class='notice'>It looks so good... But it feels so wrong to eat it before it's finished...</span>")
return
if(istype(W,/obj/item/weapon/chaoscake_layer))
var/obj/item/weapon/chaoscake_layer/C = W
if(C.layer_stage == 8)
to_chat(user, "Finally! The coin on the top, the almighty chaos cake is complete!")
qdel(W)
stage++
desc = desclist2[stage]
icon_state = "chaoscake-6"
edible = 1
name = "The Chaos Cake!"
else if(stage == maxstages)
to_chat(user, "The cake is already done!")
else if(stage == C.layer_stage)
to_chat(user, "You add another layer to the cake, nice.")
qdel(W)
stage++
desc = desclist2[stage]
icon_state = "chaoscake_stage-[stage]"
else
to_chat(user, "Hmm, doesnt seem like this layer is supposed to be added there?")
// Chaos cake
/datum/recipe/microwave/chaoscake_layerone
reagents = list("flour" = 300,"milk" = 200, "sugar" = 100, "egg" = 30)
fruit = list("poisonberries" = 15, "cherries" = 15)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/meat/,
/obj/item/weapon/reagent_containers/food/snacks/meat/,
/obj/item/weapon/reagent_containers/food/snacks/meat/,
/obj/item/weapon/reagent_containers/food/snacks/meat/
)
result = /obj/structure/chaoscake
/datum/recipe/microwave/chaoscake_layertwo
reagents = list("flour" = 300, "milk" = 200, "sugar" = 100, "egg" = 30, )
fruit = list("vanilla" = 15, "banana" = 15)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough
)
result = /obj/item/weapon/chaoscake_layer
/datum/recipe/microwave/chaoscake_layerthree
reagents = list("flour" = 240, "milk" = 150, "sugar" = 80, "egg" = 24, "deathbell" = 100)
fruit = list("grapes" = 30)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough
)
result = /obj/item/weapon/chaoscake_layer/three
/datum/recipe/microwave/chaoscake_layerfour
reagents = list("flour" = 240, "milk" = 150, "sugar" = 80, "egg" = 24, "milkshake" = 300)
fruit = list("rice" = 30)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough
)
result = /obj/item/weapon/chaoscake_layer/four
/datum/recipe/microwave/chaoscake_layerfive
reagents = list("flour" = 180, "milk" = 100, "sugar" = 60, "egg" = 18, "blood" = 300)
fruit = list("tomato" = 20)
items = list() //supposed to be made with lobster, still has to be ported.
result = /obj/item/weapon/chaoscake_layer/five
/datum/recipe/microwave/chaoscake_layersix
reagents = list("flour" = 180, "milk" = 100, "sugar" = 60, "egg" = 18, "sprinkles" = 10)
fruit = list("apple" = 30)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/chocolatebar,
/obj/item/weapon/reagent_containers/food/snacks/chocolatebar,
/obj/item/weapon/reagent_containers/food/snacks/chocolatebar
)
result = /obj/item/weapon/chaoscake_layer/six
/datum/recipe/microwave/chaoscake_layerseven
reagents = list("flour" = 120, "milk" = 50, "sugar" = 40, "egg" = 12, "devilskiss" = 200)
fruit = list("potato" = 10)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough
)
result = /obj/item/weapon/chaoscake_layer/seven
/datum/recipe/microwave/chaoscake_layereight
reagents = list("flour" = 120, "milk" = 50, "sugar" = 40, "egg" = 12, "cream" = 200)
fruit = list("lemon" = 10)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough
)
result = /obj/item/weapon/chaoscake_layer/eight
/datum/recipe/microwave/chaoscake_layernine
reagents = list("water" = 100, "blood" = 100)
fruit = list("goldapple" = 50)
items = list()
result = /obj/item/weapon/chaoscake_layer/nine
/obj/structure/chaoscake
name = "An unfinished cake"
desc = "A single layer of a strange cake, you can see the cherry paste ooze, but it feels very incomplete..."
icon = 'icons/obj/food64x64.dmi'
icon_state = "chaoscake_unfinished-1"
pixel_x = -16
var/slices = 6
var/maxslices = 6
var/stage = 1
var/maxstages = 9
var/edible = 0
var/regentime = 1000
var/interval = 0
var/static/list/desclist2 = list(
"The first layer of a strange cake, you can see the cherry paste ooze.",
"The second layer of the cake sits in place now, smelling of pear with delicious colourful cream.",
"The third layer of cake adds a strange purple layer, glazed over with frosting. It smells of grapes, but with a hint of something foul underneath.",
"With the fourth layer added the cake looks happier again. Reeking of vanilla, it brings up memories of childhood joy.",
"The fifth layer is extremely disturbing on that cake. Smelling of pure copper, it seems that bright blood clots are forming on top.",
"The cake is getting closer with the sixth layer added, the pink hue smelling of chocolate, with colourful sprinkles on top.",
"The first pair of triplets rest on the cake, despite being mostly similar to the first three, an evil aura becomes noticable.",
"The second pair of triplets rest on the cake, if you stand on the bright side, you can feel a good aura lifting your mood.",
"A chaos cake. Both a creation of dark and light, the two cakes are kept in a careful balance by that mystical coin in the middle. It's said its effects would dissipate if the balance is ever tipped in favour of one side too much, so both sides much be cut equally."
)
/obj/item/weapon/chaoscake_layer
name = "A layer of cake"
desc = "a layer of cake, it is made out of colourful cream."
icon = 'icons/obj/food.dmi'
icon_state = "chaoscake_layer-2"
var/layer_stage = 1
/obj/item/weapon/chaoscake_layer/three
desc = "a layer of cake, glazed in purple."
icon_state = "chaoscake_layer-3"
layer_stage = 2
/obj/item/weapon/chaoscake_layer/four
desc = "a layer of cake, reminding you of a colouring book."
icon_state = "chaoscake_layer-4"
layer_stage = 3
/obj/item/weapon/chaoscake_layer/five
desc = "A layer of cake, smells like copper."
icon_state = "chaoscake_layer-5"
layer_stage = 4
/obj/item/weapon/chaoscake_layer/six
desc = "A layer of cake, featuring colourful sprinkles."
icon_state = "chaoscake_layer-6"
layer_stage = 5
/obj/item/weapon/chaoscake_layer/seven
desc = "A triplet of evil cake parts."
icon_state = "chaoscake_layer-7"
layer_stage = 6
/obj/item/weapon/chaoscake_layer/eight
desc = "A triplet of good cake parts."
icon_state = "chaoscake_layer-8"
layer_stage = 7
/obj/item/weapon/chaoscake_layer/nine
name = "A coin of balance"
desc = "A very peculiar coin, it seems to stabilise the air around it."
icon_state = "chaoscake_layer-9"
layer_stage = 8
/obj/structure/chaoscake/proc/HasSliceMissing()
..()
if(slices < maxslices)
if(interval >= regentime)
interval = 0
slices++
HasSliceMissing()
else
interval++
HasSliceMissing()
else
return
/obj/item/weapon/reagent_containers/food/snacks/chaoscakeslice
name = "The Chaos Cake Slice"
desc = "A slice from The Chaos Cake, it pulses weirdly, as if angry to be seperated from the whole"
icon_state = "chaoscake_slice-1"
center_of_mass = list("x"=16, "y"=10)
nutriment_desc = list()
nutriment_amt = 4
volume = 80
/obj/item/weapon/reagent_containers/food/snacks/chaoscakeslice/Initialize()
..()
var/i = rand(1,6)
icon_state = "chaoscake_slice-[i]"
switch(i)
if(1)
name = "Slice Of Evil" //Pretty damn poisonous, takes a lot of work to make safe for consumption, useful for medical.
desc = "An odd slice, despite the grease and cherries oozing off the top, it smells delicious."
nutriment_desc = list("The desire to consume" = 10) // You won't even taste the poison.
reagents.add_reagent("neurotoxic_protein", 2)
reagents.add_reagent("shockchem", 2)
reagents.add_reagent("amatoxin", 2)
reagents.add_reagent("carpotoxin", 2)
reagents.add_reagent("spidertoxin", 2)
bitesize = 7
if(2)
name = "Slice Of Evil" //A bad trip
desc = "A mysterious slice, coated in purple frosting that smells like grapes."
nutriment_desc = list("The desire to show off an party" = 10)
reagents.add_reagent("stoxin", 2)
reagents.add_reagent("space_drugs", 10)
reagents.add_reagent("serotrotium", 4)
reagents.add_reagent("cryptobiolin", 8)
reagents.add_reagent("mindbreaker", 10)
reagents.add_reagent("psilocybin", 10)
bitesize = 30 //even a single bite won't make you escape fate.
if(3)
name = "Slice Of Evil" //acidic
desc = "A menacing slice, smelling clearly of copper, blood clots float on top."
nutriment_desc = list("Infernal Rage" = 10)
reagents.add_reagent("blood", 20)
reagents.add_reagent("stomacid", 10)
reagents.add_reagent("mutagen", 4)
reagents.add_reagent("thirteenloko", 20)
reagents.add_reagent("hyperzine", 10)
bitesize = 30
if(4)
name = "Slice Of Good" //anti-tox
desc = "A colourful slice, smelling of pear and coated in delicious cream."
nutriment_desc = list("Hapiness" = 10)
reagents.add_reagent("anti_toxin", 2)
reagents.add_reagent("tricordrazine", 2)
bitesize = 3
if(5)
name = "Slice Of Good" //anti-oxy
desc = "A light slice, it's pretty to look at and smells of vanilla."
nutriment_desc = list("Freedom" = 10)
reagents.add_reagent("dexalinp", 2)
reagents.add_reagent("tricordrazine", 2)
bitesize = 3
if(6)
name = "Slice Of Good" //anti-burn/brute
desc = "A hearty slice, it smells of chocolate and strawberries."
nutriment_desc = list("Love" = 10)
reagents.add_reagent("bicaridine", 2)
reagents.add_reagent("tricordrazine", 2)
reagents.add_reagent("kelotane", 2)
bitesize = 4
/obj/structure/chaoscake/attackby(var/obj/item/weapon/W, var/mob/living/user)
if(istype(W,/obj/item/weapon/material/knife))
if(edible == 1)
HasSliceMissing()
if(slices <= 0)
to_chat(user, "The cake hums away quietly as the chaos powered goodness slowly recovers the large amount of lost mass, best to give it a moment before cutting another slice.")
return
else
to_chat(user, "You cut a slice of the cake. The slice looks like the cake was just baked, and you can see before your eyes as the spot where you cut the slice slowly regenerates!")
slices = slices - 1
icon_state = "chaoscake-[slices]"
new /obj/item/weapon/reagent_containers/food/snacks/chaoscakeslice(src.loc)
else
to_chat(user, "<span class='notice'>It looks so good... But it feels so wrong to eat it before it's finished...</span>")
return
if(istype(W,/obj/item/weapon/chaoscake_layer))
var/obj/item/weapon/chaoscake_layer/C = W
if(C.layer_stage == 8)
to_chat(user, "Finally! The coin on the top, the almighty chaos cake is complete!")
qdel(W)
stage++
desc = desclist2[stage]
icon_state = "chaoscake-6"
edible = 1
name = "The Chaos Cake!"
else if(stage == maxstages)
to_chat(user, "The cake is already done!")
else if(stage == C.layer_stage)
to_chat(user, "You add another layer to the cake, nice.")
qdel(W)
stage++
desc = desclist2[stage]
icon_state = "chaoscake_unfinished-[stage]"
else
to_chat(user, "Hmm, doesnt seem like this layer is supposed to be added there?")
+35 -4
View File
@@ -55,6 +55,13 @@ I said no!
)
result = /obj/item/weapon/reagent_containers/food/snacks/donut/jelly
/datum/recipe/microwave/jellydonut/poisonberry
reagents = list("poisonberryjuice" = 5, "sugar" = 5)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough
)
result = /obj/item/weapon/reagent_containers/food/snacks/donut/poisonberry
/datum/recipe/microwave/jellydonut/slime
reagents = list("slimejelly" = 5, "sugar" = 5)
items = list(
@@ -308,7 +315,14 @@ I said no!
items = list(
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough,
)
result = /obj/item/weapon/reagent_containers/food/snacks/berryclafoutis
result = /obj/item/weapon/reagent_containers/food/snacks/berryclafoutis/berry
/datum/recipe/microwave/poisonberryclafoutis
fruit = list("poisonberries" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough,
)
result = /obj/item/weapon/reagent_containers/food/snacks/berryclafoutis/poison
/datum/recipe/microwave/wingfangchu
reagents = list("soysauce" = 5)
@@ -639,7 +653,7 @@ I said no!
result = /obj/item/weapon/reagent_containers/food/snacks/toastedsandwich
/datum/recipe/microwave/peanutbutterjellysandwich
reagents = list("berryjuice" = 5, "peanutbutter" = 5)
reagents = list("cherryjelly" = 5, "peanutbutter" = 5)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/slice/bread,
/obj/item/weapon/reagent_containers/food/snacks/slice/bread
@@ -1106,7 +1120,15 @@ I said no!
/obj/item/weapon/reagent_containers/food/snacks/dough
)
fruit = list("berries" = 1)
result = /obj/item/weapon/reagent_containers/food/snacks/berrymuffin
result = /obj/item/weapon/reagent_containers/food/snacks/berrymuffin/berry
/datum/recipe/microwave/poisonberrymuffin
reagents = list("milk" = 5, "sugar" = 5)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough
)
fruit = list("poisonberries" = 1)
result = /obj/item/weapon/reagent_containers/food/snacks/berrymuffin/poison
/datum/recipe/microwave/ghostmuffin
reagents = list("milk" = 5, "sugar" = 5)
@@ -1115,7 +1137,16 @@ I said no!
/obj/item/weapon/ectoplasm
)
fruit = list("berries" = 1)
result = /obj/item/weapon/reagent_containers/food/snacks/ghostmuffin
result = /obj/item/weapon/reagent_containers/food/snacks/ghostmuffin/berry
/datum/recipe/microwave/poisonghostmuffin
reagents = list("milk" = 5, "sugar" = 5)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/ectoplasm
)
fruit = list("poisonberries" = 1)
result = /obj/item/weapon/reagent_containers/food/snacks/ghostmuffin/poison
/datum/recipe/microwave/eggroll
reagents = list("soysauce" = 10)
+2 -6
View File
@@ -157,12 +157,8 @@
overlays |= plant_icon
/obj/item/weapon/reagent_containers/food/snacks/grown/Crossed(var/mob/living/M)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = M
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
if(M.is_incorporeal())
return
if(seed && seed.get_trait(TRAIT_JUICY) == 2)
if(istype(M))
+1
View File
@@ -80,6 +80,7 @@
/datum/seed/berry/poison
name = "poisonberries"
seed_name = "poison berry"
kitchen_tag = "poisonberries"
display_name = "poison berry bush"
mutants = list("deathberries")
chems = list("nutriment" = list(1), "toxin" = list(3,5), "poisonberryjuice" = list(10,5))
@@ -20,12 +20,8 @@
manual_unbuckle(user)
/obj/effect/plant/Crossed(atom/movable/O)
//VOREStation Edit begin: SHADEKIN
var/mob/SK = O
if(istype(SK))
if(SK.shadekin_phasing_check())
return
//VOREStation Edit end: SHADEKIN
if(O.is_incorporeal())
return
if(isliving(O))
trodden_on(O)
+1 -1
View File
@@ -22,7 +22,7 @@
/turf/proc/lighting_clear_overlay()
if(lighting_overlay)
qdel(lighting_overlay)
qdel(lighting_overlay, force = TRUE)
for(var/datum/lighting_corner/C in corners)
C.update_active()
+6
View File
@@ -39,6 +39,9 @@
if (SSatoms.initialized == INITIALIZATION_INSSATOMS)
return // let proper initialisation handle it later
var/prev_shuttle_queue_state = SSshuttles.block_init_queue
SSshuttles.block_init_queue = TRUE
var/list/atom/atoms = list()
var/list/area/areas = list()
var/list/obj/structure/cable/cables = list()
@@ -71,6 +74,9 @@
var/area/A = I
A.power_change()
SSshuttles.block_init_queue = prev_shuttle_queue_state
SSshuttles.process_init_queues() // We will flush the queue unless there were other blockers, in which case they will do it.
admin_notice("<span class='danger'>Submap initializations finished.</span>", R_DEBUG)
/datum/map_template/proc/load_new_z(var/centered = FALSE, var/orientation = 0)
+13
View File
@@ -0,0 +1,13 @@
/obj/structure/fans/hardlight
name = "hardlight shield"
desc = "Retains air, allows passage."
plane = TURF_PLANE
layer = ABOVE_TURF_LAYER
density = FALSE
icon = 'icons/effects/effects_vr.dmi'
icon_state = "hardlight"
buildstackamount = 2
light_range = 3
light_power = 1
light_color = "#FFFFFF"

Some files were not shown because too many files have changed in this diff Show More