Merge branch 'master' into protean-rework

This commit is contained in:
BlackMajor
2022-05-12 14:24:51 +12:00
committed by GitHub
176 changed files with 91723 additions and 34726 deletions
+11 -2
View File
@@ -34,7 +34,16 @@ Unsure where to begin contributing to Chomp Station? You can start by looking th
### Chomp Station Coding Standards
Any code submissions that do not meet our coding standards are likely to be rejected, or at the very least, have a maintainer request changes on your PR. Save time and follow these standards from the start.
Any code submissions that do not meet our coding standards are likely to be rejected, or at the very least, have a maintainer request changes on your PR. Save time and follow these standards from the start:
In an effort to make contributing easier to do, Black Major has started a modularity folder, https://github.com/CHOMPStation2/CHOMPStation2/tree/master/modular_chomp.
Ideally, any content that can be written that is wholelly independant of vorestation's content, should be
included in this modularity folder, and put into the associated folder that it would have appeared in among the standard files.
Ideally, the point of this is to make it slightly easier to differentiate chomp specific content from virgo content.
When should you use this?
Mostly for chomp exclusive stuff, otherwise if you need to modify a base file for any reason or if it is expected to be a part of upstream as well, write it in the base files with the following standards/policies/guidelines in the meantime:
* If it is something like a bugfix that VoreStation or Polaris would want (the codebases we use), code it in their code and make the PR to them. We regularly update from them. They would want any general gameplay bugfixes, and things that are obviously intended to work one way, but do not. They do not have any of our fluff species (vulp, akula, fenn, etc) so do not make PRs related to that, or any vore content to them.
* Never edit stock Polaris or Vore .DMI files. If you are confused about which .DMI files we have added and which were there originally, refer to their repository and and see if they exist (https://github.com/PolarisSS13/Polaris) (https://github.com/VOREStation/VOREStation). All PRs with edits to stock .DMI files might be rejected.
@@ -42,7 +51,7 @@ Any code submissions that do not meet our coding standards are likely to be reje
* For single-line changes: //CHOMPEdit - "Explanation" (Edit can also be Add for new lines or Removal if you are commenting the line out)
* For multi-line additions: //CHOMPEdit - "Explanation" and then at the bottom of your changes, //CHOMPEdit End
* For multi-line removals: Use a block comment (/\* xxx \*/) to comment out the existing code block (do not modify whitespace more than necessary) and at the start, it should contain /\* CHOMP Removal - "Reason"
* If it is something like a bugfix that Polaris would want (the codebase we use), you may want to consider coding it there as well. They may want any general gameplay bugfixes, and things that are obviously intended to work one way, but do not. They do not have any of our fluff species (vulp, akula, fenn, etc) so do not make PRs related to that, or any vore content to them.
* If it is something like a bugfix that Polaris or Vorestation would want (the codebase we use), you may want to consider coding it there as well. They may want any general gameplay bugfixes, and things that are obviously intended to work one way, but do not. They do not have any of our fluff species (vulp, akula, fenn, etc) so do not make PRs related to that, or any vore content to them.
* Change whitespace as little as possible. Do not randomly add/remove whitespace.
* Any new files should have "_ch" at the end. For example, "life_ch.dm". Just make them in the same location as the file they are related to.
* Map changes must be in tgm format. See the [Mapmerge2 Readme] for details, or use [StrongDMM] which can automatically save maps as tgm.
+5 -1
View File
@@ -36,6 +36,10 @@ labelPRBasedOnFilePath:
"Type: .git or .github":
- '.github/**'
- '.git/**'
# Contains changes to the TGUI bundle
"Type: TGUI Bundle":
- 'tgui/public/**'
##### Greetings ########################################################################################################
# Comment to be posted to welcome users when they open their first PR
@@ -103,4 +107,4 @@ firstIssueWelcomeComment: >
# # It helps avoid multiple heads in alembic migrations in a collaborative development project.
# - airflow/migrations/*
# - airflow/migrations/**/*
# - airflow/alembic.ini
# - airflow/alembic.ini
+9
View File
@@ -161,7 +161,16 @@
if(istype(target, /turf/simulated))
var/turf/simulated/modeled_location = target
if(modeled_location.special_temperature)//First do special interactions then the usuall stuff
var/delta_temp = modeled_location.special_temperature - air.temperature//2200C - 20C = 2180K
//assuming aluminium with thermal conductivity 235 W * K / m, Copper (400), Silver (430), steel (50), gold (320)
var/heat_gain = 23500 * 100 * delta_temp
air.add_thermal_energy(heat_gain)
if(network)
network.update = 1
if(modeled_location.blocks_air)
if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0))
+2 -1
View File
@@ -98,7 +98,8 @@
else
var/datum/gas_mixture/environment = loc.return_air()
environment_temperature = environment.temperature
if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference)
var/turf/simulated/loc_as_turf = loc
if((abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference) || (loc_as_turf.special_temperature))
parent.temperature_interact(loc, volume, thermal_conductivity)
else if(istype(loc, /turf/space/))
parent.radiate_heat_to_space(surface, 1)
+2 -1
View File
@@ -1,3 +1,4 @@
// Methods of obtaining a circuit.
#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box and able to be printed in the IC printer.
#define IC_SPAWN_RESEARCH 2 // If the circuit design will be available in the IC printer after upgrading it.
#define IC_SPAWN_RESEARCH 2 // If the circuit design will be available in the IC printer after upgrading it.
#define IC_SPAWN_ILLEGAL 3 // If the circuit design will be available if upgrading the IC printer illegally.
+88 -120
View File
@@ -1,121 +1,89 @@
// Sorted alphabetically
// Shamelessly yoinked from TGCode, luv u folks
#define span_abductor(str) ("<span class='abductor'>" + str + "</span>")
#define span_admin(str) ("<span class='admin'>" + str + "</span>")
#define span_adminhelp(str) ("<span class='adminhelp'>" + str + "</span>")
#define span_adminnotice(str) ("<span class='adminnotice'>" + str + "</span>")
#define span_adminobserverooc(str) ("<span class='adminobserverooc'>" + str + "</span>")
#define span_adminooc(str) ("<span class='adminooc'>" + str + "</span>")
#define span_adminsay(str) ("<span class='adminsay'>" + str + "</span>")
#define span_aiprivradio(str) ("<span class='aiprivradio'>" + str + "</span>")
#define span_alert(str) ("<span class='alert'>" + str + "</span>")
#define span_alertalien(str) ("<span class='alertalien'>" + str + "</span>")
#define span_alertsyndie(str) ("<span class='alertsyndie'>" + str + "</span>")
#define span_alertwarning(str) ("<span class='alertwarning'>" + str + "</span>")
#define span_alien(str) ("<span class='alien'>" + str + "</span>")
#define span_announce(str) ("<span class='announce'>" + str + "</span>")
#define span_big(str) ("<span class='big'>" + str + "</span>")
#define span_bigicon(str) ("<span class='bigicon'>" + str + "</span>")
#define span_binarysay(str) ("<span class='binarysay'>" + str + "</span>")
#define span_blue(str) ("<span class='blue'>" + str + "</span>")
#define span_blueteamradio(str) ("<span class='blueteamradio'>" + str + "</span>")
#define span_bold(str) ("<span class='bold'>" + str + "</span>")
#define span_boldannounce(str) ("<span class='boldannounce'>" + str + "</span>")
#define span_boldnotice(str) ("<span class='boldnotice'>" + str + "</span>")
#define span_boldwarning(str) ("<span class='boldwarning'>" + str + "</span>")
#define span_centcomradio(str) ("<span class='centcomradio'>" + str + "</span>")
#define span_changeling(str) ("<span class='changeling'>" + str + "</span>")
#define span_clown(str) ("<span class='clown'>" + str + "</span>")
#define span_colossus(str) ("<span class='colossus'>" + str + "</span>")
#define span_command_headset(str) ("<span class='command_headset'>" + str + "</span>")
#define span_comradio(str) ("<span class='comradio'>" + str + "</span>")
#define span_cult(str) ("<span class='cult'>" + str + "</span>")
#define span_cultbold(str) ("<span class='cultbold'>" + str + "</span>")
#define span_cultboldtalic(str) ("<span class='cultboldtalic'>" + str + "</span>")
#define span_cultitalic(str) ("<span class='cultitalic'>" + str + "</span>")
#define span_cultlarge(str) ("<span class='cultlarge'>" + str + "</span>")
#define span_danger(str) ("<span class='danger'>" + str + "</span>")
#define span_deadsay(str) ("<span class='deadsay'>" + str + "</span>")
#define span_deconversion_message(str) ("<span class='deconversion_message'>" + str + "</span>")
#define span_drone(str) ("<span class='drone'>" + str + "</span>")
#define span_engradio(str) ("<span class='engradio'>" + str + "</span>")
#define span_extremelybig(str) ("<span class='extremelybig'>" + str + "</span>")
#define span_ghostalert(str) ("<span class='ghostalert'>" + str + "</span>")
#define span_green(str) ("<span class='green'>" + str + "</span>")
#define span_greenannounce(str) ("<span class='greenannounce'>" + str + "</span>")
#define span_greenteamradio(str) ("<span class='greenteamradio'>" + str + "</span>")
#define span_greentext(str) ("<span class='greentext'>" + str + "</span>")
#define span_hear(str) ("<span class='hear'>" + str + "</span>")
#define span_hidden(str) ("<span class='hidden'>" + str + "</span>")
#define span_hierophant(str) ("<span class='hierophant'>" + str + "</span>")
#define span_hierophant_warning(str) ("<span class='hierophant_warning'>" + str + "</span>")
#define span_highlight(str) ("<span class='highlight'>" + str + "</span>")
#define span_his_grace(str) ("<span class='his_grace'>" + str + "</span>")
#define span_holoparasite(str) ("<span class='holoparasite'>" + str + "</span>")
#define span_hypnophrase(str) ("<span class='hypnophrase'>" + str + "</span>")
#define span_icon(str) ("<span class='icon'>" + str + "</span>")
#define span_info(str) ("<span class='info'>" + str + "</span>")
#define span_interface(str) ("<span class='interface'>" + str + "</span>")
#define span_looc(str) ("<span class='looc'>" + str + "</span>")
#define span_medal(str) ("<span class='medal'>" + str + "</span>")
#define span_medradio(str) ("<span class='medradio'>" + str + "</span>")
#define span_memo(str) ("<span class='memo'>" + str + "</span>")
#define span_memoedit(str) ("<span class='memoedit'>" + str + "</span>")
#define span_mind_control(str) ("<span class='mind_control'>" + str + "</span>")
#define span_minorannounce(str) ("<span class='minorannounce'>" + str + "</span>")
#define span_monkey(str) ("<span class='monkey'>" + str + "</span>")
#define span_monkeyhive(str) ("<span class='monkeyhive'>" + str + "</span>")
#define span_monkeylead(str) ("<span class='monkeylead'>" + str + "</span>")
#define span_name(str) ("<span class='name'>" + str + "</span>")
#define span_narsie(str) ("<span class='narsie'>" + str + "</span>")
#define span_narsiesmall(str) ("<span class='narsiesmall'>" + str + "</span>")
#define span_nicegreen(str) ("<span class='nicegreen'>" + str + "</span>")
#define span_notice(str) ("<span class='notice'>" + str + "</span>")
#define span_noticealien(str) ("<span class='noticealien'>" + str + "</span>")
#define span_ooc(str) ("<span class='ooc'>" + str + "</span>")
#define span_papyrus(str) ("<span class='papyrus'>" + str + "</span>")
#define span_phobia(str) ("<span class='phobia'>" + str + "</span>")
#define span_prefix(str) ("<span class='prefix'>" + str + "</span>")
#define span_purple(str) ("<span class='purple'>" + str + "</span>")
#define span_radio(str) ("<span class='radio'>" + str + "</span>")
#define span_reallybig(str) ("<span class='reallybig'>" + str + "</span>")
#define span_red(str) ("<span class='red'>" + str + "</span>")
#define span_redteamradio(str) ("<span class='redteamradio'>" + str + "</span>")
#define span_redtext(str) ("<span class='redtext'>" + str + "</span>")
#define span_resonate(str) ("<span class='resonate'>" + str + "</span>")
#define span_revenbignotice(str) ("<span class='revenbignotice'>" + str + "</span>")
#define span_revenboldnotice(str) ("<span class='revenboldnotice'>" + str + "</span>")
#define span_revendanger(str) ("<span class='revendanger'>" + str + "</span>")
#define span_revenminor(str) ("<span class='revenminor'>" + str + "</span>")
#define span_revennotice(str) ("<span class='revennotice'>" + str + "</span>")
#define span_revenwarning(str) ("<span class='revenwarning'>" + str + "</span>")
#define span_robot(str) ("<span class='robot'>" + str + "</span>")
#define span_rose(str) ("<span class='rose'>" + str + "</span>")
#define span_sans(str) ("<span class='sans'>" + str + "</span>")
#define span_sciradio(str) ("<span class='sciradio'>" + str + "</span>")
#define span_secradio(str) ("<span class='secradio'>" + str + "</span>")
#define span_servradio(str) ("<span class='servradio'>" + str + "</span>")
#define span_singing(str) ("<span class='singing'>" + str + "</span>")
#define span_slime(str) ("<span class='slime'>" + str + "</span>")
#define span_small(str) ("<span class='small'>" + str + "</span>")
#define span_smallnotice(str) ("<span class='smallnotice'>" + str + "</span>")
#define span_smallnoticeital(str) ("<span class='smallnoticeital'>" + str + "</span>")
#define span_spider(str) ("<span class='spider'>" + str + "</span>")
#define span_suicide(str) ("<span class='suicide'>" + str + "</span>")
#define span_suppradio(str) ("<span class='suppradio'>" + str + "</span>")
#define span_swarmer(str) ("<span class='swarmer'>" + str + "</span>")
#define span_syndradio(str) ("<span class='syndradio'>" + str + "</span>")
#define span_tape_recorder(str) ("<span class='tape_recorder'>" + str + "</span>")
#define span_tinynotice(str) ("<span class='tinynotice'>" + str + "</span>")
#define span_tinynoticeital(str) ("<span class='tinynoticeital'>" + str + "</span>")
#define span_unconscious(str) ("<span class='unconscious'>" + str + "</span>")
#define span_userdanger(str) ("<span class='userdanger'>" + str + "</span>")
#define span_warning(str) ("<span class='warning'>" + str + "</span>")
#define span_yell(str) ("<span class='yell'>" + str + "</span>")
#define span_yellowteamradio(str) ("<span class='yellowteamradio'>" + str + "</span>"
// VORE Specific stuff after this point
// Sorted by however I felt like it
#define span_game_say(str) ("<span class='game_say'>" + str + "</span>"
#define span_emote_subtle(str) ("<span class='emote_subtle'>" + str + "</span>"
#define span_emote(str) ("<span class='emote'>" + str + "</span>"
// We have two other ways of doing this, so why not a third. This one atleast has more span options.
#define span_ooc(str) ("<span class='ooc'>" + str + "</span>")
#define span_looc(str) ("<span class='looc'>" + str + "</span>")
#define span_deadsay(str) ("<span class='deadsay'>" + str + "</span>")
#define span_radio(str) ("<span class='radio'>" + str + "</span>")
#define span_deptradio(str) ("<span class='deptradio'>" + str + "</span>")
#define span_newscaster(str) ("<span class='newscaster'>" + str + "</span>")
#define span_comradio(str) ("<span class='comradio'>" + str + "</span>")
#define span_syndradio(str) ("<span class='syndradio'>" + str + "</span>")
#define span_centradio(str) ("<span class='centradio'>" + str + "</span>"
#define span_airadio(str) ("<span class='airadio'>" + str + "</span>")
#define span_entradio(str) ("<span class='entradio'>" + str + "</span>")
#define span_secradio(str) ("<span class='secradio'>" + str + "</span>")
#define span_engradio(str) ("<span class='engradio'>" + str + "</span>")
#define span_medradio(str) ("<span class='medradio'>" + str + "</span>")
#define span_sciradio(str) ("<span class='sciradio'>" + str + "</span>")
#define span_supradio(str) ("<span class='supradio'>" + str + "</span>"
#define span_srvradio(str) ("<span class='srvradio'>" + str + "</span>")
#define span_expradio(str) ("<span class='expradio'>" + str + "</span>")
#define span_name(str) ("<span class='name'>" + str + "</span>")
#define span_say(str) ("<span class='say'>" + str + "</span>")
#define span_alert(str) ("<span class='alert'>" + str + "</span>")
#define span_ghostalert(str) ("<span class='ghostalert'>" + str + "</span>")
#define span_emote(str) ("<span class='emote'>" + str + "</span>")
#define span_emote_subtle(str) ("<span class='emote_subtle'>" + str + "</span>")
#define span_attack(str) ("<span class='attack'>" + str + "</span>")
#define span_moderate(str) ("<span class='moderate'>" + str + "</span>")
#define span_disarm(str) ("<span class='disarm'>" + str + "</span>")
#define span_passive(str) ("<span class='passive'>" + str + "</span>")
#define span_critical(str) ("<span class='critical'>" + str + "</span>")
#define span_danger(str) ("<span class='danger'>" + str + "</span>")
#define span_warning(str) ("<span class='warning'>" + str + "</span>")
#define span_rose(str) ("<span class='rose'>" + str + "</span>")
#define span_info(str) ("<span class='info'>" + str + "</span>")
#define span_notice(str) ("<span class='notice'>" + str + "</span>")
#define span_alium(str) ("<span class='alium'>" + str + "</span>")
#define span_cult(str) ("<span class='cult'>" + str + "</span>")
#define span_reflex_shoot(str) ("<span class='reflex_shoot'>" + str + "</span>")
/* Languages */
#define span_alien(str) ("<span class='alien'>" + str + "</span>")
#define span_tajaran(str) ("<span class='tajaran'>" + str + "</span>")
#define span_tajaran_signlang(str) ("<span class='tajaran_signlang'>" + str + "</span>")
#define span_akhani(str) ("<span class='akhani'>" + str + "</span>")
#define span_skrell(str) ("<span class='skrell'>" + str + "</span>")
#define span_skrellfar(str) ("<span class='skrellfar'>" + str + "</span>")
#define span_soghun(str) ("<span class='soghun'>" + str + "</span>")
#define span_solcom(str) ("<span class='solcom'>" + str + "</span>")
#define span_changeling(str) ("<span class='changeling'>" + str + "</span>")
#define span_sergal(str) ("<span class='sergal'>" + str + "</span>")
#define span_birdsongc(str) ("<span class='birdsongc'>" + str + "</span>")
#define span_vulpkanin(str) ("<span class='vulpkanin'>" + str + "</span>")
#define span_enochian(str) ("<span class='enochian'>" + str + "</span>")
#define span_daemon(str) ("<span class='daemon'>" + str + "</span>")
#define span_bug(str) ("<span class='bug'>" + str + "</span>")
#define span_vox(str) ("<span class='vox'>" + str + "</span>")
#define span_zaddat(str) ("<span class='zaddat'>" + str + "</span>")
#define span_promethean(str) ("<span class='promethean'>" + str + "</span>")
#define span_rough(str) ("<span class='rough'>" + str + "</span>")
#define span_say_quote(str) ("<span class='say_quote'>" + str + "</span>")
#define span_terminus(str) ("<span class='terminus'>" + str + "</span>")
#define span_interface(str) ("<span class='interface'>" + str + "</span>")
#define span_spacer(str) ("<span class='spacer'>" + str + "</span>")
#define span_blob(str) ("<span class='blob'>" + str + "</span>")
#define span_debug_error(str) ("<span class='debug_error'>" + str + "</span>")
#define span_debug_warning(str) ("<span class='debug_warning'>" + str + "</span>")
#define span_debug_info(str) ("<span class='debug_info'>" + str + "</span>")
#define span_debug_debug(str) ("<span class='debug_debug'>" + str + "</span>")
#define span_debug_trace(str) ("<span class='debug_trace'>" + str + "</span>")
#define span_black(str) ("<span class='black'>" + str + "</span>")
#define span_darkgray(str) ("<span class='darkgray'>" + str + "</span>")
#define span_gray(str) ("<span class='gray'>" + str + "</span>")
#define span_red(str) ("<span class='red'>" + str + "</span>")
#define span_orange(str) ("<span class='orange'>" + str + "</span>")
#define span_blue(str) ("<span class='blue'>" + str + "</span>")
#define span_green(str) ("<span class='green'>" + str + "</span>")
+1
View File
@@ -111,6 +111,7 @@
#define NO_TALK_MSG 128 // Do not show the "\The [speaker] talks into \the [radio]" message
#define NO_STUTTER 256 // No stuttering, slurring, or other speech problems
#define ALT_TRANSMIT 512 // Language is not based on vision or sound (Todo: add this into the say code and use it for the rootspeak languages)
#define INAUDIBLE 1024 // Language is not audible (similar to nonverbal) but is still using hearing-based recognition
#define SKIN_NORMAL 0
#define SKIN_THREAT 1
+1
View File
@@ -12,6 +12,7 @@
#define LANGUAGE_SPACER "Spacer"
#define LANGUAGE_CLOWNISH "Coulrian"
#define LANGUAGE_TAVAN "Tavan"
#define LANGUAGE_ECHOSONG "Echo Song"
#define LANGUAGE_CHIMPANZEE "Chimpanzee"
#define LANGUAGE_NEAERA "Neaera"
+2 -2
View File
@@ -151,9 +151,9 @@ Proc for attack log creation, because really why not
/proc/get_exposed_defense_zone(var/atom/movable/target)
var/obj/item/weapon/grab/G = locate() in target
if(G && G.state >= GRAB_NECK) //works because mobs are currently not allowed to upgrade to NECK if they are grabbing two people.
return pick("head", "l_hand", "r_hand", "l_foot", "r_foot", "l_arm", "r_arm", "l_leg", "r_leg")
return pick(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_FOOT, BP_R_FOOT, BP_L_ARM, BP_R_ARM, BP_L_LEG, BP_R_LEG)
else
return pick("chest", "groin")
return pick(BP_TORSO, BP_GROIN)
/proc/do_mob(mob/user , mob/target, time = 30, target_zone = 0, uninterruptible = FALSE, progress = TRUE, ignore_movement = FALSE, exclusive = FALSE)
if(!user || !target)
@@ -0,0 +1,167 @@
/client
var/datum/managed_browser/changelingevolution/changelingevolution = null
/datum/managed_browser/changelingevolution
base_browser_id = "evolution_tree"
title = "Evolution Tree"
size_x = 480
size_y = 600
var/textbody = null
/datum/managed_browser/changelingevolution/New(client/new_client)
if(!new_client.mob || !new_client.mob.mind || !new_client.mob.mind.changeling)
message_admins("[new_client] tried to access changeling evolutions while not changeling.")
qdel(src)
..()
/datum/managed_browser/changelingevolution/Destroy()
if(my_client)
my_client.changelingevolution = null
return ..()
/datum/managed_browser/changelingevolution/get_html()
var/list/dat = list("<html><body>")
var/geneticpoints_current = my_client.mob.mind.changeling.geneticpoints
var/geneticpoints_max = my_client.mob.mind.changeling.max_geneticpoints
dat += "<center>Genetic Points Available: [geneticpoints_current] / [geneticpoints_max] <br>"
dat += "Obtain more by feeding on your own kind. <br> <hr>"
dat += "<a style='background-color:#c72121;' href='?src=\ref[src];tutorial=1'>What am I?</a><br><hr>"
dat += "<a style='background-color:#c72121;' href='?src=\ref[src];inherent=1'>Inherent</a>"
dat += "<a style='background-color:#c72121;' href='?src=\ref[src];armor=1'>Armor</a>"
dat += "<a style='background-color:#c72121;' href='?src=\ref[src];weapons=1'>Weapons</a>"
dat += "<a style='background-color:#c72121;' href='?src=\ref[src];stings=1'>Stings</a>"
dat += "<a style='background-color:#c72121;' href='?src=\ref[src];shrieks=1'>Shrieks</a>"
dat += "<a style='background-color:#c72121;' href='?src=\ref[src];health=1'>Health</a>"
dat += "<a style='background-color:#c72121;' href='?src=\ref[src];enhancements=1'>Enhancements</a></center>"
if(textbody)
dat += "<table border='1' style='width:100%; background-color:#000000;'>"
dat += "[textbody]"
dat += "</table>"
dat += "</body></html>"
return dat.Join()
/datum/managed_browser/changelingevolution/Topic(href, href_list[])
if(!my_client)
return FALSE
if(href_list["close"])
return
if(href_list["inherent"])
generate_abilitylist(CHANGELING_POWER_INHERENT)
if(href_list["armor"])
generate_abilitylist(CHANGELING_POWER_ARMOR)
if(href_list["weapons"])
generate_abilitylist(CHANGELING_POWER_WEAPONS)
if(href_list["stings"])
generate_abilitylist(CHANGELING_POWER_STINGS)
if(href_list["shrieks"])
generate_abilitylist(CHANGELING_POWER_SHRIEKS)
if(href_list["health"])
generate_abilitylist(CHANGELING_POWER_HEALTH)
if(href_list["enhancements"])
generate_abilitylist(CHANGELING_POWER_ENHANCEMENTS)
if(href_list["evolve"])
var/datum/mind/M = my_client.mob.mind
var/datum/changeling/C = my_client.mob.mind.changeling
var/datum/power/changeling/Thepower = href_list["evolve"]
for (var/datum/power/changeling/P in powerinstances)
if(P.name == Thepower)
Thepower = P
break
if(!istype(M))
return
if(Thepower == null)
to_chat(M.current, "Purchase failed. Inform a dev of this error.")
return
if(Thepower in C.purchased_powers)
to_chat(M.current, "You already have this ability! Inform a dev of this error.") /// Should not be possible
return
if(C.geneticpoints < Thepower.genomecost)
to_chat(M.current, "We cannot evolve this... yet. We must acquire more DNA.")
return
C.purchased_powers += Thepower /// Set it to purchased
C.geneticpoints -= Thepower.genomecost
generate_abilitylist(Thepower.power_category) /// Refresh the UI
my_client.mob.mind.changeling.purchasePower(M, Thepower)
if(href_list["tutorial"])
textbody = "<tr><th><font color='#c72121'><center>What am I?</center></font><br></th></tr>"
textbody += "<tr><td>"
textbody += "<font color='#F7F7ED'>You are a changeling, a creature empowered with genetic-based abilities that change your body in bizarre ways."
textbody += " It's probably best the crew doesn't know about your power -- at least not right away.</font><br><br>"
textbody += "<font color='#F7F7ED'>What a changeling <i>is</i>, however, is up to you. Are you a strange alien impersonating crew? Are you a"
textbody += " normal crewmember infected with a parasite? An experiment gone wrong? It's up to you to make the story.</font><br><br>"
textbody += "<font color='#F7F7ED'>Of course, you need to know how it works to begin with.</font><br><br>"
textbody += "<font color='#F7F7ED'>Your abilities cost chemicals that your body will slowly regenerate with varying speeds based on enhancements obtained."
textbody += " There are a set of inherent abilities you will always have while the rest may be purchased through genomes.</font><br><br>"
textbody += "<font color='#F7F7ED'>You may obtain more genomes if you find another changeling and absorb them, but this is not required. If you've found "
textbody += "your abilities aren't to your liking, you have up to two re-adapts available, and these may be refilled by absorbing anyone -- including monkeys.</font><br><br>"
textbody += "<font color='#F7F7ED'>Good luck and remember, killing isn't always the end goal.</font>"
display()
/datum/managed_browser/changelingevolution/proc/generate_abilitylist(cat)
var/list/ability_list = list()
var/info = ""
var/catname = ""
for(var/datum/power/changeling/P in powerinstances)
if(P.power_category == cat)
ability_list[++ability_list.len] = P
switch(cat)
if(CHANGELING_POWER_INHERENT)
catname = "Inherent"
info = "These powers are inherent to your kind and will always be accessible, provided you have the chemicals to use them."
if(CHANGELING_POWER_ARMOR)
catname = "Armor"
info = "These abilities will provide you with space protection -- and potentially armor."
if(CHANGELING_POWER_WEAPONS)
catname = "Weapons"
info = "These abilities will provide you the means to fight back."
if(CHANGELING_POWER_STINGS)
catname = "Stings"
info = "These abilities provide the means to sting organic beings for various effects -- though you must be close enough, and they must have exposed flesh."
if(CHANGELING_POWER_SHRIEKS)
catname = "Shrieks"
info = "These abilities enhance your vocal chords, empowering your screams."
if(CHANGELING_POWER_HEALTH)
catname = "Health"
info = "These abilities will enhance your health or aid you in mending your wounds."
if(CHANGELING_POWER_ENHANCEMENTS)
catname = "Enhancements"
info = "These abilities enhance you in various ways."
create_textbody(ability_list, catname, info)
/datum/managed_browser/changelingevolution/proc/create_textbody(ability_list, cat, catinfo)
textbody = "<tr><th><font color='#c72121'><center>[cat] Skills</font><br></th></tr>"
textbody += "<tr><td><font color='#F7F7ED'>[catinfo]</center></font><br><hr></td></tr>"
for(var/A in ability_list)
var/datum/power/changeling/powerdata = A
textbody += "<tr><td><center><font color='#c72121'><b>[initial(powerdata.name)]</b></font><br></center>"
textbody += "<font color='#F7F7ED'>[initial(powerdata.desc)]</font><br><br>"
textbody += "<font color='#F7F7ED'><i>[powerdata.helptext]</i></font><br>"
if(powerdata.enhancedtext != "")
textbody += "<font color='#F7F7ED'><b>WHEN EHANCED: </b><i>[powerdata.enhancedtext]</i></font><br>"
if(powerdata in my_client.mob.mind.changeling.purchased_powers)
textbody += "<center><font color='#F7F7ED'><i><b>This ability is already evolved!</b></i></font></center>"
else if(cat != "Inherent")
textbody += "<center>Cost: [powerdata.genomecost]</center>"
textbody += "<center><a style='background-color:#c72121;' href='?src=\ref[src];evolve=[A]'>Evolve</a></center>"
textbody += "</td></tr>"
display()
@@ -26,6 +26,13 @@
/obj/item/clothing/head/radiation = 3
)
/datum/supply_pack/eng/dosimeter
contains = list(/obj/item/weapon/storage/box/dosimeter = 6)
name = "Dosimeters"
cost = 10
containertype = /obj/structure/closet/crate
containername = "dosimeter crate"
/datum/supply_pack/eng/algae
contains = list(/obj/item/stack/material/algae/ten)
name = "Algae Sheets (10)"
+4 -2
View File
@@ -24,14 +24,16 @@
/proc/randmutb(var/mob/living/M)
if(!M) return
M.dna.check_integrity()
var/block = pick(GLASSESBLOCK,COUGHBLOCK,FAKEBLOCK,NERVOUSBLOCK,CLUMSYBLOCK,TWITCHBLOCK,HEADACHEBLOCK,BLINDBLOCK,DEAFBLOCK,HALLUCINATIONBLOCK)
//var/block = pick(GLASSESBLOCK,COUGHBLOCK,FAKEBLOCK,NERVOUSBLOCK,CLUMSYBLOCK,TWITCHBLOCK,HEADACHEBLOCK,BLINDBLOCK,DEAFBLOCK,HALLUCINATIONBLOCK) // Most of these are disabled anyway.
var/block = pick(FAKEBLOCK,CLUMSYBLOCK,BLINDBLOCK,DEAFBLOCK)
M.dna.SetSEState(block, 1)
// Give Random Good Mutation to M
/proc/randmutg(var/mob/living/M)
if(!M) return
M.dna.check_integrity()
var/block = pick(HULKBLOCK,XRAYBLOCK,FIREBLOCK,TELEBLOCK,NOBREATHBLOCK,REMOTEVIEWBLOCK,REGENERATEBLOCK,INCREASERUNBLOCK,REMOTETALKBLOCK,MORPHBLOCK,BLENDBLOCK,NOPRINTSBLOCK,SHOCKIMMUNITYBLOCK,SMALLSIZEBLOCK)
//var/block = pick(HULKBLOCK,XRAYBLOCK,FIREBLOCK,TELEBLOCK,NOBREATHBLOCK,REMOTEVIEWBLOCK,REGENERATEBLOCK,INCREASERUNBLOCK,REMOTETALKBLOCK,MORPHBLOCK,BLENDBLOCK,NOPRINTSBLOCK,SHOCKIMMUNITYBLOCK,SMALLSIZEBLOCK) // Much like above, most of these blocks are disabled in code.
var/block = pick(HULKBLOCK,XRAYBLOCK,FIREBLOCK,TELEBLOCK,REGENERATEBLOCK,REMOTETALKBLOCK)
M.dna.SetSEState(block, 1)
// Random Appearance Mutation
+3 -2
View File
@@ -24,7 +24,7 @@
var/languages=null
var/list/flavor=null
var/gender = null
var/list/body_descriptors = null
var/list/body_descriptors = null // Guess we'll keep null.
var/list/genetic_modifiers = list() // Modifiers with the MODIFIER_GENETIC flag are saved. Note that only the type is saved, not an instance.
/datum/dna2/record/proc/GetData()
@@ -54,7 +54,8 @@
newrecord.implant = implant
newrecord.flavor = flavor
newrecord.gender = gender
newrecord.body_descriptors = body_descriptors.Copy()
if(body_descriptors)
newrecord.body_descriptors = body_descriptors.Copy()
newrecord.genetic_modifiers = genetic_modifiers.Copy()
return newrecord
@@ -107,6 +107,9 @@
/obj/machinery/computer/guestpass/attackby(obj/I, mob/user)
if(istype(I, /obj/item/weapon/card/id/guest))
to_chat(user, "<span class='warning'>The guest pass terminal denies to accept the guest pass.</span>")
return
if(istype(I, /obj/item/weapon/card/id))
if(!giver && user.unEquip(I))
I.forceMove(src)
@@ -47,4 +47,4 @@
/decl/poster/tg_10
name = "Hacking Guide"
desc = "This poster details the internal workings of the common NanoTrasen airlock."
icon_state="poster10"
icon_state="poster10"
@@ -0,0 +1,4 @@
/decl/poster/tg_11 //CHOMPedit
name = "Post This Ratvar"
desc = "This poster seems to have an animated image on it. Truly an advancement in the wonders of technology."
icon_state = "postvar"
@@ -0,0 +1,73 @@
var/global/list/global_used_pois = list()
/obj/effect/landmark/poi_loader
name = "PoI Loader"
var/size_x
var/size_y
var/poi_type = null
var/remove_from_pool = TRUE
/obj/effect/landmark/poi_loader/New()
INITIALIZE_IMMEDIATE(/obj/effect/landmark/poi_loader)
/obj/effect/landmark/poi_loader/Initialize()
src.load_poi()
return ..()
/obj/effect/landmark/poi_loader/proc/get_turfs_to_clean()
return block(locate(src.x, src.y, src.z), locate((src.x + size_x - 1), (src.y + size_y - 1), src.z))
/obj/effect/landmark/poi_loader/proc/annihilate_bounds()
//var/deleted_atoms = 0
//admin_notice("<span class='danger'>Annihilating objects in poi loading location.</span>", R_DEBUG)
var/list/turfs_to_clean = get_turfs_to_clean()
if(turfs_to_clean.len)
for(var/x in 1 to 2) // Requires two passes to get everything.
for(var/turf/T in turfs_to_clean)
for(var/atom/movable/AM in T)
//++deleted_atoms
qdel(AM)
//admin_notice("<span class='danger'>Annihilated [deleted_atoms] objects.</span>", R_DEBUG)
/obj/effect/landmark/poi_loader/proc/load_poi()
var/turf/T = get_turf(src)
if(!isturf(T))
to_world_log("[log_info_line(src)] not on a turf! Cannot place poi template.")
return
// Choose a poi
if(!poi_type)
return
if(!(global_used_pois.len) || !(global_used_pois[poi_type]))
global_used_pois[poi_type] = list()
var/list/poi_list = global_used_pois[poi_type]
for(var/map in SSmapping.map_templates)
var/template = SSmapping.map_templates[map]
if(istype(template, poi_type))
poi_list += template
var/datum/map_template/template_to_use = null
var/list/our_poi_list = global_used_pois[poi_type]
if(!our_poi_list.len)
return
else
template_to_use = pick(our_poi_list)
if(!template_to_use)
return
//admin_notice("<span class='danger'>Chosen Predefined PoI Map: [chosen_type.name]</span>", R_DEBUG)
if(remove_from_pool)
global_used_pois[poi_type] -= template_to_use
// Annihilate movable atoms
annihilate_bounds()
//CHECK_TICK //Don't let anything else happen for now
// Actually load it
template_to_use.load(T)
@@ -340,6 +340,11 @@
if("toggle_ringer")
ringer = !ringer
if("set_ringer_tone")
var/ringtone = tgui_input_text(usr, "Set Ringer Tone", "Ringer")
if(ringtone)
ttone = ringtone
if("selfie_mode")
selfie_mode = !selfie_mode
@@ -75,6 +75,20 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
// If you turn this on, it changes the way communicator video works. User configurable option.
var/selfie_mode = FALSE
// Ringtones! (Based on the PDA ones)
var/ttone = "beep" //The ringtone!
var/list/ttone_sound = list("beep" = 'sound/machines/twobeep.ogg',
"boom" = 'sound/effects/explosionfar.ogg',
"slip" = 'sound/misc/slip.ogg',
"honk" = 'sound/items/bikehorn.ogg',
"SKREE" = 'sound/voice/shriek1.ogg',
// "holy" = 'sound/items/PDA/ambicha4-short.ogg',
"xeno" = 'sound/voice/hiss1.ogg',
"dust" = 'sound/effects/supermatter.ogg',
"spark" = 'sound/effects/sparks4.ogg',
"rad" = 'sound/items/geiger/high1.ogg',
"servo" = 'sound/machines/rig/rigservo.ogg')
// Proc: New()
// Parameters: None
// Description: Adds the new communicator to the global list of all communicators, sorts the list, obtains a reference to the Exonet node, then tries to
@@ -76,9 +76,15 @@
return
if(ringer)
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
var/S
if(ttone in ttone_sound)
S = ttone_sound[ttone]
else
S = 'sound/machines/twobeep.ogg'
playsound(src, S, 50, 1)
for (var/mob/O in hearers(2, loc))
O.show_message(text("[bicon(src)] *beep*"))
O.show_message(text("[bicon(src)] *[ttone]*"))
alert_called = 1
update_icon()
+38 -1
View File
@@ -43,7 +43,7 @@ GLOBAL_LIST_BOILERPLATE(all_pai_cards, /obj/item/device/paicard)
return ..()
var/pai_name = input(user, "Choose your character's name", "Character Name") as text
var/actual_pai_name = sanitize_name(pai_name)
var/actual_pai_name = sanitize_name(pai_name, ,1)
if(isnull(actual_pai_name))
return ..()
@@ -360,3 +360,40 @@ GLOBAL_LIST_BOILERPLATE(all_pai_cards, /obj/item/device/paicard)
var/rendered = "<span class='message'>[msg]</span>"
pai.show_message(rendered, type)
..()
// VoreEdit: Living Machine Stuff after this.
// This adds a var and proc for all machines to take a pAI. (The pAI can't control anything, it's just for RP.)
// You need to add usage of the proc to each machine to actually add support. For an example of this, see code\modules\food\kitchen\microwave.dm
/obj/machinery
var/obj/item/device/paicard/paicard = null
/obj/machinery/proc/insertpai(mob/user, obj/item/device/paicard/card)
//var/obj/item/paicard/card = I
var/mob/living/silicon/pai/AI = card.pai
if(paicard)
to_chat(user, span_notice("This bot is already under PAI Control!"))
return
if(!istype(card)) // TODO: Add sleevecard support.
return
if(!card.pai)
to_chat(user, span_notice("This card does not currently have a personality!"))
return
paicard = card
user.unEquip(card)
card.forceMove(src)
AI.client.eye = src
to_chat(AI, span_notice("Your location is [card.loc].")) // DEBUG. TODO: Make unfolding the chassis trigger an eject.
name = AI.name
to_chat(AI, span_notice("You feel a tingle in your circuits as your systems interface with \the [initial(src.name)]."))
/obj/machinery/proc/ejectpai(mob/user)
if(paicard)
var/mob/living/silicon/pai/AI = paicard.pai
paicard.forceMove(src.loc)
AI.client.eye = AI
paicard = null
name = initial(src.name)
to_chat(AI, span_notice("You feel a tad claustrophobic as your mind closes back into your card, ejecting from \the [initial(src.name)]."))
if(user)
to_chat(user, span_notice("You eject the card from \the [initial(src.name)]."))
+2 -2
View File
@@ -240,7 +240,7 @@ HALOGEN COUNTER - Radcount on mobs
continue
// Broken limbs
if(e.status & ORGAN_BROKEN)
if((e.name in list("l_arm", "r_arm", "l_leg", "r_leg", "head", "chest", "groin")) && (!e.splinted))
if((e.name in list(BP_L_ARM, BP_R_ARM, BP_L_LEG, BP_R_LEG, BP_HEAD, BP_TORSO, BP_GROIN)) && (!e.splinted))
fracture_dat += "<span class='warning'>Unsecured fracture in subject [e.name]. Splinting recommended for transport.</span><br>"
else if(advscan >= 1 && showadvscan == 1)
fracture_dat += "<span class='warning'>Bone fractures detected in subject [e.name].</span><br>"
@@ -277,7 +277,7 @@ HALOGEN COUNTER - Radcount on mobs
dat += "<span class='danger'>Warning: Blood Level LOW: [blood_percent]% [blood_volume]cl. Type: [blood_type]</span><br>"
else
dat += "<span class='notice'>Blood Level Normal: [blood_percent]% [blood_volume]cl. Type: [blood_type]</span><br>"
dat += "<span class='notice'>Subject's pulse: <font color='[H.pulse == PULSE_THREADY || H.pulse == PULSE_NONE ? "red" : "blue"]'>[H.get_pulse(GETPULSE_TOOL)] bpm.</font></span><br>" // CHOMP/VORE Edit: Missed a linebreak here.
dat += "<span class='notice'>Subject's pulse: <font color='[H.pulse == PULSE_THREADY || H.pulse == PULSE_NONE ? "red" : "blue"]'>[H.get_pulse(GETPULSE_TOOL)] bpm.</font></span><br>" // VORE Edit: Missed a linebreak here.
if(istype(H.species, /datum/species/xenochimera)) // VOREStation Edit Start: Visible feedback for medmains on Xenochimera.
if(H.stat == DEAD && H.revive_ready == REVIVING_READY && !H.hasnutriment())
dat += "<span class='danger'>WARNING: Protein levels low. Subject incapable of reconstitution.</span>"
@@ -0,0 +1,48 @@
/obj/item/selectable_item
name = "selectable item"
desc = "If you find this, you should definitely report this..."
icon = 'icons/obj/items.dmi'
icon_state = "gift1"
var/preface_string = "You are about to select an item. Are you sure you want to use it and select one?"
var/preface_title = "selectable item"
var/selection_string = "Select an item:"
var/selection_title = "Item Selection"
var/list/item_options = list("Gift" = /obj/item/weapon/a_gift,
"Health Analyzer" = /obj/item/device/healthanalyzer)
/obj/item/selectable_item/attack_self(mob/user as mob)
tgui_alert(user, {"[preface_string]"}, preface_title)
var/chosen_item = tgui_input_list(usr, selection_string, selection_title, item_options)
chosen_item = item_options[chosen_item]
if(chosen_item)
user.drop_item()
var/obj/item/result = new chosen_item(get_turf(user))
user.put_in_active_hand(result)
result.add_fingerprint(user)
qdel(src)
return
/obj/item/selectable_item/chemistrykit
icon = 'icons/obj/chemical_vr.dmi'
icon_state = "chemkit"
selection_string = "Select a chemical:"
selection_title = "Chemical Selection"
/obj/item/selectable_item/chemistrykit/size
name = "size chemistry kit"
desc = "A pre-arranged home chemistry kit. This one is for rather specific set of size-altering chemicals."
preface_string = "This kit can be used to create a vial of a size-altering chemical, but there's only enough material for one."
preface_title = "Size Chemistry Kit"
item_options = list("Macrocillin" = /obj/item/weapon/reagent_containers/glass/beaker/vial/macrocillin,
"Microcillin" = /obj/item/weapon/reagent_containers/glass/beaker/vial/microcillin,
"Normalcillin" = /obj/item/weapon/reagent_containers/glass/beaker/vial/normalcillin)
/obj/item/selectable_item/chemistrykit/gender
name = "gender chemistry kit"
desc = "A pre-arranged home chemistry kit. This one is for rather specific set of gender-altering chemicals."
preface_string = "This kit can be used to create a vial of a gender-altering chemical, but there's only enough material for one."
preface_title = "Gender Chemistry Kit"
item_options = list("Androrovir" = /obj/item/weapon/reagent_containers/glass/beaker/vial/androrovir,
"Gynorovir" = /obj/item/weapon/reagent_containers/glass/beaker/vial/gynorovir,
"Androgynorovir" = /obj/item/weapon/reagent_containers/glass/beaker/vial/androgynorovir)
+22 -9
View File
@@ -1,13 +1,6 @@
// Porting stack dragging/auto stacking from TG.
/obj/item/stack/proc/merge(obj/item/stack/S) //Merge src into S, as much as possible
if(uses_charge || S.uses_charge) // This should realistically never happen, but in case it does lets avoid breaking things.
return
if(S.stacktype != stacktype)
return
if(S.amount >= S.max_amount)
return
var/transfer = get_amount()
transfer = min(transfer, S.max_amount - S.amount)
if(pulledby)
@@ -18,7 +11,27 @@
use(transfer)
S.add(transfer)
/obj/item/stack/proc/can_merge(obj/item/stack/S)
if(uses_charge || S.uses_charge) // This should realistically never happen, but in case it does lets avoid breaking things.
return
if(S.stacktype != stacktype)
return
if(S.amount >= S.max_amount)
return
if(!isturf(loc) || !isturf(S.loc))
return FALSE
if(src == S)
return FALSE
if(ismob(S.loc) || ismob(loc))
return FALSE
if(S.throwing || throwing)
return FALSE
if(S.amount < 1 || amount < 1)
return FALSE
return TRUE
/obj/item/stack/Crossed(var/atom/movable/AM)
if(isturf(AM.loc) && AM != src && istype(AM, src.type) && !AM.throwing)
merge(AM)
if(istype(AM, src.type)) // Sanity so we don't try to merge non-stacks.
if(can_merge(AM))
merge(AM)
return ..()
@@ -203,9 +203,6 @@
name = T_BOARD("sensors console")
build_path = /obj/machinery/computer/ship/sensors
/obj/item/weapon/circuitboard/area_atmos
name = T_BOARD("area air control console")
build_path = /obj/machinery/computer/area_atmos
@@ -224,4 +221,9 @@
/obj/item/weapon/circuitboard/shutoff_monitor
name = T_BOARD("automatic shutoff valve monitor")
build_path = /obj/machinery/computer/shutoff_monitor
origin_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4)
origin_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4)
/obj/item/weapon/circuitboard/stockexchange
name = T_BOARD("stock exchange console")
build_path = /obj/machinery/computer/stockexchange
origin_tech = list(TECH_DATA = 2, TECH_MAGNET = 1)
@@ -14,7 +14,7 @@
max_storage_space = INVENTORY_POUCH_SPACE
can_hold = null
pocketable = TRUE
var/insert_delay = 0 SECONDS
var/remove_delay = 2 SECONDS
@@ -32,7 +32,7 @@
// No delay if you have the pouch in your hands
if(user.get_active_hand() == src || user.get_inactive_hand() == src)
return TRUE // Skip delay
if(remove_delay && !do_after(user, remove_delay, src, needhand = TRUE, exclusive = TASK_USER_EXCLUSIVE))
return FALSE // Moved while there is a delay
@@ -58,10 +58,10 @@
/obj/item/weapon/storage/pouch/ammo
name = "storage pouch (ammo)"
desc = "This storage pouch can be used to provide some additional storage for quick access. Can only hold ammunition and cells."
desc = "This storage pouch can be used to provide some additional storage for quick access. Can only hold ammunition, cells, explosives, and grenades."
icon_state = "ammo"
max_storage_space = INVENTORY_POUCH_SPACE
can_hold = list(/obj/item/ammo_magazine, /obj/item/ammo_casing, /obj/item/weapon/cell/device/weapon)
can_hold = list(/obj/item/ammo_magazine, /obj/item/ammo_casing, /obj/item/weapon/cell/device/weapon, /obj/item/weapon/grenade, /obj/item/weapon/plastique) //Vorestation Add - make it more useful for non-sec/explo
/obj/item/weapon/storage/pouch/eng_tool
name = "storage pouch (tools)"
@@ -69,15 +69,35 @@
icon_state = "engineering_tool"
max_storage_space = INVENTORY_POUCH_SPACE
can_hold = list(
/obj/item/weapon/tool,
/obj/item/weapon/tool/crowbar,
/obj/item/weapon/tool/screwdriver,
/obj/item/weapon/weldingtool,
/obj/item/weapon/tool/wirecutters,
/obj/item/weapon/tool/wrench,
/obj/item/device/multitool,
/obj/item/device/flashlight,
/obj/item/weapon/cell/device,
/obj/item/stack/cable_coil,
/obj/item/device/t_scanner,
/obj/item/device/analyzer,
/obj/item/clothing/glasses,
/obj/item/clothing/gloves,
)
/obj/item/device/pda,
/obj/item/device/megaphone,
/obj/item/taperoll,
/obj/item/device/radio/headset,
/obj/item/device/robotanalyzer,
/obj/item/weapon/material/minihoe,
/obj/item/weapon/material/knife/machete/hatchet,
/obj/item/device/analyzer/plant_analyzer,
/obj/item/weapon/extinguisher/mini,
/obj/item/weapon/tape_roll,
/obj/item/device/integrated_electronics/wirer,
/obj/item/device/integrated_electronics/debugger,
/obj/item/weapon/shovel/spade,
/obj/item/stack/nanopaste,
/obj/item/device/geiger
) //Vorestation Add - make it the same as the tool-belt why was it not like this to start with wtf
/obj/item/weapon/storage/pouch/eng_supply
name = "storage pouch (supplies)"
@@ -88,15 +108,19 @@
/obj/item/weapon/cell/device,
/obj/item/stack/cable_coil,
/obj/item/taperoll,
/obj/item/weapon/extinguisher/mini,
/obj/item/weapon/tape_roll
)
/obj/item/weapon/extinguisher,
/obj/item/weapon/tape_roll,
/obj/item/stack/material/steel,
/obj/item/stack/material/glass,
/obj/item/device/lightreplacer,
/obj/item/weapon/cell
) //Vorestation Add - makes it actually useful lmao, adds sheets and cells as well as light replacers and lets you take any extinguisher that fits
/obj/item/weapon/storage/pouch/eng_parts
name = "storage pouch (parts)"
desc = "This storage pouch can be used to provide some additional storage for quick access. Can only hold machinery components."
icon_state = "part_pouch"
max_storage_space = INVENTORY_POUCH_SPACE
max_storage_space = INVENTORY_POUCH_SPACE*2 //Vorestation Add - yeah lemme give up my pocket to hold FOUR CAPACITORS or have an inferior box... now you can hold eight in your pocket so its at least a box
can_hold = list(
/obj/item/weapon/stock_parts,
/obj/item/stack/cable_coil,
@@ -120,8 +144,20 @@
/obj/item/weapon/storage/pill_bottle,
/obj/item/stack/medical,
/obj/item/weapon/reagent_containers/hypospray,
/obj/item/weapon/storage/quickdraw/syringe_case
)
/obj/item/weapon/storage/quickdraw/syringe_case,
/obj/item/weapon/syringe_cartridge,
/obj/item/clothing/gloves/sterile,
/obj/item/device/sleevemate,
/obj/item/bodybag,
/obj/item/clothing/mask/surgical,
/obj/item/weapon/soap,
/obj/item/stack/nanopaste,
/obj/item/taperoll/medical,
/obj/item/weapon/storage/box/freezer,
/obj/item/clothing/mask/chewable/candy/lolli,
) //Vorestation add - added a bunch of misc medical stuff
max_storage_space = ITEMSIZE_COST_SMALL*3 //Vorestation Add - makes it slightly smaller since its a lot of stuff with pocket access
remove_delay = 5 //Vorestation Add - .5 second delay, get the medical things faster because there is no reason to use this otherwise. still gotta stop moving to take things out.
/obj/item/weapon/storage/pouch/flares
name = "storage pouch (flares)"
@@ -145,7 +181,7 @@
desc = "This storage pouch can be used to provide some additional storage for quick access. Can hold one normal sized weapon."
icon_state = "pistol_holster"
storage_slots = 1
can_hold = list(/obj/item/weapon/gun)
can_hold = list(/obj/item/weapon/gun) //this covers basically everything I think so its fine
remove_delay = 0
/obj/item/weapon/storage/pouch/holster/full_stunrevolver
starts_with = list(/obj/item/weapon/gun/energy/stunrevolver)
@@ -159,11 +195,11 @@
..()
/obj/item/weapon/storage/pouch/baton
name = "storage pouch (baton)"
desc = "This storage pouch can be used to provide some additional storage for quick access. Can hold one standard baton."
name = "storage pouch (melee)"
desc = "This storage pouch can be used to provide some additional storage for quick access. Can hold one normal size melee." //Vorestation add - make it a melee pouch literally why would you hold ONE BATON
icon_state = "baton_holster"
storage_slots = 1
can_hold = list(/obj/item/weapon/melee/baton)
can_hold = list(/obj/item/weapon/melee, /obj/item/weapon/material, /obj/item/weapon/tool/wrench) //should be like, every melee weapon I could think of that was normal size. Can make it more specific if needed. Also wrench because I thought it was funny.
remove_delay = 0
/obj/item/weapon/storage/pouch/baton/full
starts_with = list(/obj/item/weapon/melee/baton)
+112
View File
@@ -0,0 +1,112 @@
//Spawner subtypes where the result begins with anomalous properties, primarily for PoI use.
/obj/random/maintenance/anom
name = "random anomalous clutter"
desc = "This is a random maintenance-style item with anomalous properties."
icon_state = "anomaly"
/obj/random/maintenance/anom/item_to_spawn()
return pick(prob(300);/obj/random/tech_supply/anom,
prob(200);/obj/random/medical/anom,
prob(100);/obj/random/firstaid/anom,
prob(10);/obj/random/contraband/anom,
prob(50);/obj/random/action_figure/anom,
prob(50);/obj/random/plushie/anom,
prob(200);/obj/random/junk/anom,
prob(200);/obj/random/material/anom,
prob(50);/obj/random/toy/anom,
prob(100);/obj/random/tank/anom,
prob(50);/obj/random/soap/anom,
prob(60);/obj/random/drinkbottle/anom,
prob(500);/obj/random/maintenance/clean/anom)
//Guns
/obj/random/gun/random/anomalous
name = "random anomalous weapon"
desc = "This is a random energy or ballistic weapon with anomalous properties."
start_anomalous = TRUE
/obj/random/gun/random/anomalous/item_to_spawn()
return pick(prob(5);/obj/random/energy/anom,
prob(5);/obj/random/projectile/random/anom)
/obj/random/energy/anom
start_anomalous = TRUE
/obj/random/projectile/random/anom
start_anomalous = TRUE
//Misc objects
/obj/random/tech_supply/anom
start_anomalous = TRUE
/obj/random/medical/anom
start_anomalous = TRUE
/obj/random/firstaid/anom
start_anomalous = TRUE
/obj/random/contraband/anom
start_anomalous = TRUE
/obj/random/action_figure/anom
start_anomalous = TRUE
/obj/random/plushie/anom
start_anomalous = TRUE
/obj/random/junk/anom
start_anomalous = TRUE
/obj/random/material/anom
start_anomalous = TRUE
/obj/random/material/anom
start_anomalous = TRUE
/obj/random/toy/anom
start_anomalous = TRUE
/obj/random/tank/anom
start_anomalous = TRUE
/obj/random/soap/anom
start_anomalous = TRUE
/obj/random/drinkbottle/anom
start_anomalous = TRUE
/obj/random/maintenance/clean/anom
start_anomalous = TRUE
/obj/random/technology_scanner/anom
start_anomalous = TRUE
/obj/random/powercell/anom
start_anomalous = TRUE
/obj/random/tool/anom
start_anomalous = TRUE
/obj/random/tool/power/anom
start_anomalous = TRUE
/obj/random/toolbox/anom
start_anomalous = TRUE
/obj/random/tech_supply/component/anom
start_anomalous = TRUE
/obj/random/medical/lite/anom
start_anomalous = TRUE
/obj/random/tank/anom
start_anomalous = TRUE
/obj/random/coin/anom
start_anomalous = TRUE
/obj/random/mug/anom
start_anomalous = TRUE
+28 -1
View File
@@ -132,6 +132,9 @@
prob(1);/obj/item/capture_crystal/random,
prob(1);/obj/random/unidentified_medicine
)
/obj/random/mainttoyloot/nofail
spawn_nothing_percentage = 0
/obj/random/maintenance/misc //Clutter and loot for maintenance and away missions
name = "random maintenance item"
@@ -150,7 +153,7 @@
prob(300);/obj/random/maintenance/security,
prob(300);/obj/random/maintenance/security,
prob(50);/obj/random/maintenance/morestuff,
prob(25);/obj/random/mainttoyloot,
prob(25);/obj/random/mainttoyloot/nofail,
prob(10);/obj/random/maintenance/foodstuff)
/obj/random/maintenance/foodstuff
@@ -188,3 +191,27 @@
prob(1);/obj/item/weapon/flame/lighter/random,
prob(1);/obj/item/weapon/storage/wallet/random,
prob(1);/obj/random/cutout)
/obj/random/instrument
name = "random instrument"
desc = "This is a random instrument."
icon = 'icons/obj/musician.dmi'
icon_state = "violin"
spawn_nothing_percentage = 0
/obj/random/instrument/item_to_spawn()
return pick(prob(5);/obj/item/instrument/violin,
prob(5);/obj/item/instrument/banjo,
prob(5);/obj/item/instrument/guitar,
prob(5);/obj/item/instrument/eguitar,
prob(5);/obj/item/instrument/accordion,
prob(5);/obj/item/instrument/trumpet,
prob(5);/obj/item/instrument/saxophone,
prob(5);/obj/item/instrument/trombone,
prob(5);/obj/item/instrument/recorder,
prob(5);/obj/item/instrument/harmonica,
prob(1);/obj/item/instrument/bikehorn,
prob(5);/obj/item/instrument/piano_synth,
prob(5);/obj/item/instrument/glockenspiel,
prob(1);/obj/item/instrument/musicalmoth
)
+1 -1
View File
@@ -128,7 +128,7 @@
new /obj/item/stack/rods(get_turf(src))
Destroy()
/obj/structure/catwalk/Crossed(atom/movable/AM as mob|obj)
/obj/structure/catwalk/Crossed(atom/movable/AM)
. = ..()
if(isliving(AM) && !AM.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)
@@ -242,6 +242,42 @@
if((. = ..()))
playsound(src, 'sound/machines/shutdown.ogg', 60, 1)
///////////////////
//// COMPUTERS ////
///////////////////
/obj/structure/salvageable/console
name = "console"
icon_state = "console0"
salvageable_parts = list(
/obj/item/stack/cable_coil{amount = 5} = 90,
/obj/item/stack/material/glass{amount = 5} = 70,
/obj/item/trash/material/circuit = 60,
/obj/item/trash/material/metal = 60,
/obj/item/weapon/stock_parts/capacitor = 40,
/obj/item/weapon/stock_parts/capacitor = 40,
/obj/item/weapon/stock_parts/scanning_module = 40,
/obj/item/weapon/stock_parts/scanning_module = 40
)
/obj/structure/salvageable/personal/Initialize()
. = ..()
icon_state = "console[rand(0,2)]"
/obj/structure/salvageable/shuttle_console
name = "shuttle console"
icon_state = "shuttle"
salvageable_parts = list(
/obj/item/stack/cable_coil{amount = 5} = 90,
/obj/item/stack/material/glass{amount = 5} = 70,
/obj/item/trash/material/circuit = 60,
/obj/item/trash/material/metal = 60,
/obj/item/weapon/stock_parts/capacitor = 40,
/obj/item/weapon/stock_parts/capacitor = 40,
/obj/item/weapon/stock_parts/scanning_module = 40,
/obj/item/weapon/stock_parts/scanning_module = 40
)
//////////////////
//// ONE STAR ////
//////////////////
@@ -254,7 +254,8 @@
prob(2);/obj/item/weapon/storage/box/syndie_kit/spy,
prob(2);/obj/item/weapon/grenade/anti_photon,
prob(2);/obj/item/clothing/under/hyperfiber/bluespace,
prob(2);/obj/item/weapon/reagent_containers/glass/beaker/vial/amorphorovir,
prob(2);/obj/item/selectable_item/chemistrykit/size,
prob(2);/obj/item/selectable_item/chemistrykit/gender,
prob(1);/obj/item/clothing/suit/storage/vest/heavy/merc,
prob(1);/obj/item/device/nif/bad,
prob(1);/obj/item/device/radio_jammer,
+1
View File
@@ -16,6 +16,7 @@
var/can_start_dirty = TRUE // If false, cannot start dirty roundstart
var/dirty_prob = 2 // Chance of being dirty roundstart
var/dirt = 0
var/special_temperature //Used for turf HE-Pipe interaction
// This is not great.
/turf/simulated/proc/wet_floor(var/wet_val = 1)
+1 -1
View File
@@ -38,7 +38,7 @@ GLOBAL_LIST_EMPTY(fancy_shuttles)
icon = 'icons/turf/fancy_shuttles/generic_preview.dmi'
icon_state = "floors"
plane = PLATING_PLANE
layer = ABOVE_TURF_LAYER
layer = DISPOSAL_LAYER
alpha = 90
/obj/effect/fancy_shuttle_floor_preview/Initialize()
+1
View File
@@ -102,6 +102,7 @@
edge_blending_priority = -2
movement_cost = 8
depth = 2
special_temperature = T0C - 5.5 //as cool as the atmosphere outside, if someone asks, its the phoron solved in the water that stops the freezing
/turf/simulated/floor/water/pool
name = "pool"
@@ -117,6 +117,11 @@
..()
gear_tweaks += gear_tweak_free_color_choice
/datum/gear/accessory/dosimeter
display_name = "Dosimeter"
path = /obj/item/weapon/storage/box/dosimeter
description = "A small device that will display dangerous levels of radiation."
/*
Talon pin
*/
@@ -74,3 +74,8 @@
display_name = "bluespace bracelet"
path = /obj/item/clothing/gloves/bluespace
cost = 5
/datum/gear/utility/walkpod
display_name = "podzu music player"
path = /obj/item/device/walkpod
cost = 2
@@ -0,0 +1,132 @@
/obj/item/clothing/accessory/dosimeter
name = "dosimeter"
desc = "A small device used to measure body radiation and warning one after a certain threshold. \
Read manual before use! Can be held, attached to the uniform or worn around the neck."
w_class = ITEMSIZE_SMALL
icon = 'icons/inventory/accessory/item_vr.dmi'
icon_override = 'icons/inventory/accessory/item_vr.dmi'
icon_state = "dosimeter"
item_state = "dosimeter"
overlay_state = "dosimeter"
slot_flags = SLOT_TIE
var/obj/item/weapon/dosimeter_film/current_film = null
/obj/item/clothing/accessory/dosimeter/New()
..()
current_film = new /obj/item/weapon/dosimeter_film(src)
update_state(current_film.state)
START_PROCESSING(SSobj, src)
/obj/item/clothing/accessory/dosimeter/Destroy()
return ..()
/obj/item/clothing/accessory/dosimeter/process()
check_holder()
if(current_film.state > 1)
STOP_PROCESSING(SSobj, src)
/obj/item/clothing/accessory/dosimeter/attack_hand(mob/user as mob)
if(user.get_inactive_hand() == src)
if(current_film)
user.put_in_hands(current_film)
current_film = null
to_chat(user, "<span class='notice'>You pulled out the film out of \the [src].</span>")
desc = "This seems like a dosimeter, but there is no film inside."
STOP_PROCESSING(SSobj, src)
update_state(0)
return
..()
else
return ..()
/obj/item/clothing/accessory/dosimeter/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/dosimeter_film))
if(!current_film)
user.drop_item()
I.loc = src
current_film = I
update_state(current_film.state)
to_chat(user, "<span class='notice'>You inserted the film into \the [src].</span>")
desc = "This seems like a dosimeter. It has a film inside."
if(current_film.state < 2)
START_PROCESSING(SSobj, src)
else
to_chat(user, "<span class='notice'>\The [src] already has a film inside.</span>")
else
return ..()
/obj/item/clothing/accessory/dosimeter/proc/check_holder()
if(wearer)
if(current_film && (wearer.radiation >= 25) && (current_film.state == 0))
update_state(1)
visible_message("<span class='warning'>The film of \the [src] starts to darken.</span>")
desc = "This seems like a dosimeter, but the film has darkened."
sleep(30)
else if(current_film && (wearer.radiation >= 50) && (current_film.state == 1))
visible_message("<span class='warning'>The film of \the [src] has turned black!</span>")
update_state(2)
desc = "This seems like a dosimeter, but the film has turned black."
/obj/item/clothing/accessory/dosimeter/proc/update_state(var/tostate)
if(current_film)
current_film.state = tostate
icon_state = "[initial(icon_state)][tostate]"
current_film.icon_state = "dosimeter_film[tostate]"
else
icon_state = "[initial(icon_state)]-empty"
update_icon()
/obj/item/weapon/dosimeter_film
name = "dosimeter film"
desc = "These films can be inserted into dosimeters. It turns from white to black, depending on how much radiation it endured."
w_class = ITEMSIZE_SMALL
icon = 'icons/inventory/accessory/item_vr.dmi'
icon_override = 'icons/inventory/accessory/item_vr.dmi'
icon_state = "dosimeter_film0"
var/state = 0 //0 - White, 1 - Darker, 2 - Black (same as iconstates)
/obj/item/weapon/dosimeter_film/proc/update_state(var/tostate)
icon_state = tostate
update_icon()
/obj/item/weapon/paper/dosimeter_manual
name = "Dosimeter manual"
info = {"<h4>Dosimeter</h4>
<h5>Usage</h5>
<ol>
<li>Insert film into dosimeter.</li>
<li>Attach dosimeter to clothing or carry it.</li>
<li>Replace film if current film turned black.</li>
</ol>
<br />
<h5>Purpose</h5>
<p>This device will let you know about any dangerous radiation levels, that your body is exposed to.
A white film indicates that everything is alright. A darker film indicates, that the radiation level is starting to get dangerous for your body.
The body has absorbed too much radiation if the film turned black.</p>"}
/obj/item/weapon/storage/box/dosimeter
name = "dosimeter case"
desc = "This case can only hold the Dosimeter, a few films and a manual."
item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
storage_slots = 5
can_hold = list(/obj/item/weapon/paper/dosimeter_manual, /obj/item/clothing/accessory/dosimeter, /obj/item/weapon/dosimeter_film)
max_storage_space = (ITEMSIZE_COST_SMALL * 2) + (ITEMSIZE_COST_TINY * 3)
w_class = ITEMSIZE_SMALL
/obj/item/weapon/storage/box/dosimeter/New()
..()
new /obj/item/weapon/paper/dosimeter_manual(src)
new /obj/item/clothing/accessory/dosimeter(src)
new /obj/item/weapon/dosimeter_film(src)
new /obj/item/weapon/dosimeter_film(src)
new /obj/item/weapon/dosimeter_film(src)
+1 -4
View File
@@ -228,13 +228,10 @@
emote_message_3p_target = "trills at TARGET."
emote_sound = 'sound/voice/teshtrill.ogg' // Copyright CC BY-NC 3.0 Arnaud Coutancier (freesound.org) for the source audio.
//CHOMPEdit Add Start
/decl/emote/audible/prbt
key = "prbt"
emote_message_1p = "You prbt."
emote_message_3p = "prbts."
emote_message_1p_target = "You prbt at TARGET."
emote_message_3p_target = "prbts at TARGET."
emote_sound = 'sound/voice/prbt.ogg'
//CHOMPEdit Add End
emote_sound = 'sound/voice/prbt.ogg'
+1 -1
View File
@@ -11,7 +11,7 @@
. = ..()
/decl/emote/human/deathgasp/get_emote_message_3p(var/mob/living/carbon/human/user)
return "USER [user.species.get_death_message(user)]"
return "[user.species.get_death_message(user)]"
/decl/emote/human/swish
key = "swish"
+6
View File
@@ -0,0 +1,6 @@
/obj/item/weapon/reagent_containers/glass/bottle/sorbitol
name = "sorbitol bottle"
desc = "A small bottle of sorbitol. Sickeningly sweet."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-3"
prefill = list("sorbitol" = 60)
@@ -206,7 +206,7 @@
var/obj/item/organ/external/E
var/nopain
if(ishuman(victim) && user.zone_sel.selecting != "groin" && user.zone_sel.selecting != "chest")
if(ishuman(victim) && user.zone_sel.selecting != BP_GROIN && user.zone_sel.selecting != BP_TORSO)
var/mob/living/carbon/human/H = victim
E = H.get_organ(user.zone_sel.selecting)
if(!E || E.species.flags & NO_PAIN)
+42 -19
View File
@@ -22,7 +22,7 @@
var/global/list/acceptable_items // List of the items you can put in
var/global/list/available_recipes // List of the recipes you can use
var/global/list/acceptable_reagents // List of the reagents you can put in
var/global/max_n_of_items = 20
var/appliancetype = MICROWAVE
var/datum/looping_sound/microwave/soundloop
@@ -36,7 +36,7 @@
/obj/machinery/microwave/Initialize()
. = ..()
reagents = new/datum/reagents(100)
reagents.my_atom = src
@@ -47,7 +47,7 @@
for(var/datum/recipe/typepath as anything in subtypesof(/datum/recipe))
if((initial(typepath.appliance) & appliancetype))
available_recipes += new typepath
acceptable_items = new
acceptable_reagents = new
for (var/datum/recipe/recipe in available_recipes)
@@ -66,6 +66,8 @@
soundloop = new(list(src), FALSE)
/obj/machinery/microwave/Destroy()
if(paicard)
ejectpai() // Lets not delete the pAI.
QDEL_NULL(soundloop)
return ..()
@@ -125,7 +127,8 @@
to_chat(user, "<span class='warning'>It's dirty!</span>")
return 1
else if(is_type_in_list(O,acceptable_items))
if(contents.len>=(max_n_of_items + component_parts.len + circuit_item_capacity)) //Adds component_parts to the maximum number of items. changed 1 to actually just be the circuit item capacity var.
var/list/workingList = cookingContents()
if(workingList.len>=(max_n_of_items + circuit_item_capacity)) //Adds component_parts to the maximum number of items. changed 1 to actually just be the circuit item capacity var.
to_chat(user, "<span class='warning'>This [src] is full of ingredients, you cannot put more.</span>")
return 1
if(istype(O, /obj/item/stack) && O:get_amount() > 1) // This is bad, but I can't think of how to change it
@@ -180,6 +183,9 @@
to_chat(user, "<span class='notice'>You decide not to do that.</span>")
else if(default_part_replacement(user, O))
return
else if(istype(O, /obj/item/device/paicard))
if(!paicard)
insertpai(user, O)
else
to_chat(user, "<span class='warning'>You have no idea what you can cook with this [O].</span>")
..()
@@ -192,6 +198,10 @@
attack_hand(user)
/obj/machinery/microwave/attack_hand(mob/user as mob)
if(user.a_intent == I_GRAB)
if(paicard)
ejectpai(user)
return
user.set_machine(src)
tgui_interact(user)
@@ -211,7 +221,7 @@
data["operating"] = operating
data["dirty"] = dirty == 100
data["items"] = get_items_list()
return data
/obj/machinery/microwave/proc/get_items_list()
@@ -220,7 +230,8 @@
var/list/items_counts = list()
var/list/items_measures = list()
var/list/items_measures_p = list()
for(var/obj/O in ((contents - component_parts) - circuit))
//for(var/obj/O in ((contents - component_parts) - circuit))
for(var/obj/O in cookingContents())
var/display_name = O.name
if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/egg))
items_measures[display_name] = "egg"
@@ -283,7 +294,7 @@
if("dispose")
dispose()
return TRUE
/*
/*
/obj/machinery/microwave/interact(mob/user as mob) // The microwave Menu
var/dat = ""
if(src.broken > 0)
@@ -352,7 +363,7 @@
if(stat & (NOPOWER|BROKEN))
return
start()
if(reagents.total_volume==0 && !(locate(/obj) in ((contents - component_parts) - circuit))) //dry run
if(reagents.total_volume==0 && !(locate(/obj) in cookingContents())) //dry run
if(!wzhzhzh(16)) //VOREStation Edit - Quicker Microwaves (Undone during Auroraport, left note in case of reversion, was 5)
abort()
return
@@ -387,7 +398,7 @@
cooked = fail()
cooked.forceMove(src.loc)
return
//Making multiple copies of a recipe
var/halftime = round(recipe.time*4/10/2) // VOREStation Edit - Quicker Microwaves (Undone during Auroraport, left note in case of reversion, was round(recipe.time/20/2))
if(!wzhzhzh(halftime))
@@ -430,7 +441,7 @@
for(var/obj/item/weapon/reagent_containers/food/snacks/S in cooked_items)
reagents.trans_to_holder(S.reagents, total/cooked_items.len)
for(var/obj/item/weapon/reagent_containers/food/snacks/S in contents)
for(var/obj/item/weapon/reagent_containers/food/snacks/S in cookingContents())
S.cook()
dispose(0) //clear out anything left
@@ -448,7 +459,7 @@
/obj/machinery/microwave/proc/has_extra_item() //- coded to have different microwaves be able to handle different items
if(item_level == 0)
for (var/obj/O in ((contents - component_parts) - circuit))
for (var/obj/O in cookingContents())
if ( \
!istype(O,/obj/item/weapon/reagent_containers/food) && \
!istype(O, /obj/item/weapon/grown) \
@@ -456,7 +467,7 @@
return 1
return 0
if(item_level == 1)
for (var/obj/O in ((contents - component_parts) - circuit))
for (var/obj/O in cookingContents())
if ( \
!istype(O, /obj/item/weapon/reagent_containers/food) && \
!istype(O, /obj/item/weapon/grown) && \
@@ -480,7 +491,7 @@
icon_state = "mw"
SStgui.update_uis(src)
soundloop.stop()
/obj/machinery/microwave/proc/stop()
playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
operating = FALSE // Turn it off again aferwards
@@ -490,7 +501,7 @@
soundloop.stop()
/obj/machinery/microwave/proc/dispose(var/message = 1)
for (var/atom/movable/A in ((contents-component_parts)-circuit))
for (var/atom/movable/A in cookingContents())
A.forceMove(loc)
if (src.reagents.total_volume)
src.dirty++
@@ -524,11 +535,12 @@
src.operating = 0 // Turn it off again aferwards
SStgui.update_uis(src)
soundloop.stop()
src.ejectpai() // If it broke, time to yeet the PAI.
/obj/machinery/microwave/proc/fail()
var/obj/item/weapon/reagent_containers/food/snacks/badrecipe/ffuu = new(src)
var/amount = 0
for (var/obj/O in (((contents - ffuu) - component_parts) - circuit))
for (var/obj/O in cookingContents() - ffuu)
amount++
if(O.reagents)
var/id = O.reagents.get_master_reagent_id()
@@ -555,14 +567,14 @@
if(!do_after(usr, 1 SECONDS, target = src))
return
if(operating)
to_chat(usr, "<span class='warning'>You can't do that, [src] door is locked!</span>")
return
usr.visible_message(
"<span class='notice'>[usr] opened [src] and has taken out [english_list(((contents-component_parts)-circuit))].</span>" ,
"<span class='notice'>You have opened [src] and taken out [english_list(((contents-component_parts)-circuit))].</span>"
"<span class='notice'>[usr] opened [src] and has taken out [english_list(cookingContents())].</span>" ,
"<span class='notice'>You have opened [src] and taken out [english_list(cookingContents())].</span>"
)
dispose()
@@ -591,7 +603,7 @@
/obj/item/weapon/holder
)
result = /obj/effect/decal/cleanable/blood/gibs
/datum/recipe/splat/before_cook(obj/container)
if(istype(container, /obj/machinery/microwave))
var/obj/machinery/microwave/M = container
@@ -614,3 +626,14 @@
var/obj/machinery/microwave/M = container
M.muck_finish()
. = ..()
/obj/machinery/microwave/proc/cookingContents() //VOREEdit, this is a better way to deal with the contents of a microwave, since the previous method is stupid.
var/list/workingList = contents.Copy() // Using the copy proc because otherwise the two lists seem to become soul bonded.
workingList -= component_parts
workingList -= circuit
if(paicard)
workingList -= paicard
for(var/M in workingList)
if(istype(M, circuit)) // Yes, we remove circuit twice. Yes, it's necessary. Yes, it's stupid.
workingList -= M
return workingList
@@ -376,7 +376,7 @@
if(battery)
var/lost = battery.use(amount * CELLRATE)
net_power -= lost
return lost > 0
return lost
return FALSE
// Ditto for giving.
@@ -11,11 +11,21 @@
var/debug = FALSE // If true, metal is infinite.
var/upgraded = FALSE // When hit with an upgrade disk, will turn true, allowing it to print the higher tier circuits.
var/illegal_upgraded = FALSE // When hit with an illegal upgrade disk, will turn true, allowing it to print the illegal circuits.
var/can_clone = FALSE // Same for above, but will allow the printer to duplicate a specific assembly. (Not implemented)
// var/static/list/recipe_list = list()
var/obj/item/device/electronic_assembly/assembly_to_clone = null // Not implemented x3
var/dirty_items = FALSE
/obj/item/device/integrated_circuit_printer/all_upgrades
upgraded = TRUE
illegal_upgraded = TRUE
can_clone = TRUE
/obj/item/device/integrated_circuit_printer/illegal
illegal_upgraded = TRUE
can_clone = TRUE
/obj/item/device/integrated_circuit_printer/upgraded
upgraded = TRUE
can_clone = TRUE
@@ -24,6 +34,7 @@
name = "fractal integrated circuit printer"
desc = "A portable(ish) machine that makes modular circuitry seemingly out of thin air."
upgraded = TRUE
illegal_upgraded = TRUE
can_clone = TRUE
debug = TRUE
@@ -68,6 +79,16 @@
attack_self(user)
return TRUE
if(istype(O,/obj/item/weapon/disk/integrated_circuit/upgrade/illegal))
if(illegal_upgraded)
to_chat(user, span("warning", "\The [src] already has this upgrade."))
return TRUE
to_chat(user, span("notice", "You install \the [O] into \the [src]."))
illegal_upgraded = TRUE
dirty_items = TRUE
attack_self(user)
return TRUE
if(istype(O,/obj/item/weapon/disk/integrated_circuit/upgrade/clone))
if(can_clone)
to_chat(user, span("warning", "\The [src] already has this upgrade."))
@@ -110,6 +131,8 @@
"name" = category,
"items" = null
)
if(cat_obj["name"] == "Illegal Parts" && !illegal_upgraded)
continue
var/list/circuit_list = SScircuit.circuit_fabricator_recipe_list[category]
var/list/items = list()
for(var/path in circuit_list)
@@ -212,6 +235,12 @@
name = "integrated circuit printer upgrade disk - advanced designs"
desc = "Install this into your integrated circuit printer to enhance it. This one adds new, advanced designs to the printer."
/obj/item/weapon/disk/integrated_circuit/upgrade/illegal
name = "integrated circuit printer upgrade disk - illegal designs"
desc = "Install this into your integrated circuit printer to enhance it. This one adds new, but illegal designs to the printer."
icon_state = "upgrade_disk_illegal"
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 4, TECH_ILLEGAL = 1)
// To be implemented later.
/obj/item/weapon/disk/integrated_circuit/upgrade/clone
name = "integrated circuit printer upgrade disk - circuit cloner"
@@ -215,7 +215,7 @@
assembly.give_power(amount)
else
var/amount = assembly.draw_power(throughput)
IO.add_avail(amount)
IO.add_avail(amount / CELLRATE)
set_pin_data(IC_OUTPUT, 1, IO.avail())
set_pin_data(IC_OUTPUT, 2, IO.surplus())
@@ -0,0 +1,89 @@
/obj/item/integrated_circuit/cryptography
complexity = 3
inputs = list("input" = IC_PINTYPE_STRING)
outputs = list("result" = IC_PINTYPE_STRING)
activators = list("compute" = IC_PINTYPE_PULSE_IN, "on computed" = IC_PINTYPE_PULSE_OUT)
category_text = "Cryptography"
power_draw_per_use = 10
// HASH FUNCTIONS
/obj/item/integrated_circuit/cryptography/hash_md5
name = "MD5 hash circuit"
desc = "Message-Digest Algorithm 5"
extended_desc = "This circuit will take a string input and generates the MD5 hash of it."
icon_state = "template"
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/cryptography/hash_md5/do_work()
var/result = ""
for(var/datum/integrated_io/I in inputs)
I.pull_data()
if(!isnull(I.data))
result = md5(I.data)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/cryptography/hash_sha1
name = "SHA1 hash circuit"
desc = "Secure Hash Algorithm 1"
extended_desc = "This circuit will take a string input and generates the SHA1 hash of it."
icon_state = "template"
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 20
/obj/item/integrated_circuit/cryptography/hash_sha1/do_work()
var/result = ""
for(var/datum/integrated_io/I in inputs)
I.pull_data()
if(!isnull(I.data))
result = sha1(I.data)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// ENCRYPTION/DECRYPTION
/obj/item/integrated_circuit/cryptography/rot13
name = "rot13 circuit"
desc = "A very simple encryption circuit."
extended_desc = "The 'rotation' field will default to 13 if no custom number is supplied. This circuit rotates every letter by X in the alphabet."
icon_state = "template"
inputs = list(
"input" = IC_PINTYPE_STRING,
"rotation" = IC_PINTYPE_NUMBER
)
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/cryptography/rot13/do_work()
var/result = ""
var/input = get_pin_data(IC_INPUT, 1)
var/rotation = get_pin_data(IC_INPUT, 2)
var/string_len = length(input)
if(!isnum(rotation))
rotation = 13
for(var/i = 1, i <= string_len, i++)
var/ascii = text2ascii(input, i)
if(ascii >= 65 && ascii <= 90)
ascii += rotation
if(ascii > 90)
ascii -= 26
else if(ascii >= 97 && ascii <= 122)
ascii += rotation
if(ascii > 122)
ascii -= 26
result += ascii2text(ascii)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
@@ -0,0 +1,121 @@
/obj/item/integrated_circuit/illegal
complexity = 3
category_text = "Illegal Parts"
power_draw_per_use = 50
/* [WIP]
/obj/item/integrated_circuit/illegal/EPv2_Spoofer
name = "\improper EPv2 Spoofer circuit"
desc = "Enables the receiving of messages of other Exonet devices."
extended_desc = "An EPv2 address is a string with the format of XXXX:XXXX:XXXX:XXXX. Data can be received using the \
second pin, with additonal data reserved for the third pin. When a message is received, the second activation pin \
will pulse whatever's connected to it. Pulsing the first activation pin will set the given EPv2 address.\
\
Note: Receiving messages could cause the circuit to accidentally send malformed data to the target address."
icon_state = "signal_illegal"
complexity = 6
inputs = list("target EPv2 address" = IC_PINTYPE_STRING)
outputs = list(
"address received" = IC_PINTYPE_STRING,
"data received" = IC_PINTYPE_STRING,
"secondary text received" = IC_PINTYPE_STRING
)
activators = list("set spoof address" = IC_PINTYPE_PULSE_IN, "on data received" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH|IC_SPAWN_ILLEGAL
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2, TECH_BLUESPACE = 2, TECH_ILLEGAL = 2)
power_draw_per_use = 200
var/datum/exonet_protocol/exonet = null
var/address_spoofed = FALSE
/obj/item/integrated_circuit/illegal/EPv2_Spoofer/New()
..()
exonet = new(src)
exonet.make_address("EPv2_Spoofer_circuit-\ref[src]")
desc += "<br>This circuit's EPv2 address is: [exonet.address]"
/obj/item/integrated_circuit/illegal/EPv2_Spoofer/Destroy()
if(exonet)
if(!address_spoofed) // We dont actually want to destroy the regular address
exonet.remove_address()
qdel(exonet)
exonet = null
return ..()
/obj/item/integrated_circuit/illegal/EPv2_Spoofer/do_work()
var/target_address = get_pin_data(IC_INPUT, 1)
exonet.address = target_address
address_spoofed = TRUE
/obj/item/integrated_circuit/illegal/receive_exonet_message(var/atom/origin_atom, var/origin_address, var/message, var/text)
set_pin_data(IC_OUTPUT, 1, origin_address)
set_pin_data(IC_OUTPUT, 2, message)
set_pin_data(IC_OUTPUT, 3, text)
push_data()
activate_pin(2)
if(address_spoofed)
var/random = rand(1,100)
if(random > 70)
exonet.send_message(origin_address, message, "[random]")
*/
/obj/item/integrated_circuit/illegal/EPv2_Discoverer
name = "\improper EPv2 Discovery circuit"
desc = "Finds all Exonet devices currently connected to the node (even if not publicly listed)."
extended_desc = "An EPv2 address is a string with the format of XXXX:XXXX:XXXX:XXXX. Data can be received using the \
second pin, with additonal data reserved for the third pin. When a message is received, the second activation pin \
will pulse whatever's connected to it. Pulsing the first activation pin will set the given EPv2 address.\
\
Note: Discovering Exonet Devices sends off a ping to each device, making it a 'noisy' circuit."
icon_state = "signal_illegal"
complexity = 3
outputs = list("addresses found" = IC_PINTYPE_LIST)
activators = list("start discovery" = IC_PINTYPE_PULSE_IN, "on addresses found" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_ILLEGAL
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2, TECH_BLUESPACE = 2, TECH_ILLEGAL = 1)
power_draw_per_use = 300
var/datum/exonet_protocol/exonet = null
var/obj/machinery/exonet_node/node = null
/obj/item/integrated_circuit/illegal/EPv2_Discoverer/proc/get_connection_to_tcomms()
if(node && node.on)
return can_telecomm(src,node)
return 0
/obj/item/integrated_circuit/illegal/EPv2_Discoverer/New()
..()
exonet = new(src)
exonet.make_address("EPv2_Discovery_circuit-\ref[src]")
desc += "<br>This circuit's EPv2 address is: [exonet.address]"
node = get_exonet_node()
message_admins("A EPv2 Discovery circuit has been created. \ref[src]")
/obj/item/integrated_circuit/illegal/EPv2_Discoverer/Destroy()
if(exonet)
exonet.remove_address()
qdel(exonet)
exonet = null
return ..()
/obj/item/integrated_circuit/illegal/EPv2_Discoverer/do_work()
if(!get_connection_to_tcomms())
set_pin_data(IC_OUTPUT, 1, null)
push_data()
activate_pin(2)
else
var/list/addresses = list()
for(var/datum/exonet_protocol/target_exonet in all_exonet_connections)
if(target_exonet.address && istext(target_exonet.address))
var/random = rand(200,350)
random = random / 10
exonet.send_message(target_exonet.address, "text", "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
addresses += target_exonet.address
set_pin_data(IC_OUTPUT, 1, addresses)
push_data()
activate_pin(2)
@@ -420,7 +420,7 @@
name = "\improper EPv2 circuit"
desc = "Enables the sending and receiving of messages on the Exonet with the EPv2 protocol."
extended_desc = "An EPv2 address is a string with the format of XXXX:XXXX:XXXX:XXXX. Data can be send or received using the \
second pin on each side, with additonal data reserved for the third pin. When a message is received, the second activaiton pin \
second pin on each side, with additonal data reserved for the third pin. When a message is received, the second activation pin \
will pulse whatever's connected to it. Pulsing the first activation pin will send a message.\
\
When messaging Communicators, you must set data to send to the string `text` to avoid errors in reception."
@@ -441,12 +441,19 @@
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2, TECH_BLUESPACE = 2)
power_draw_per_use = 50
var/datum/exonet_protocol/exonet = null
var/obj/machinery/exonet_node/node = null
/obj/item/integrated_circuit/input/EPv2/proc/get_connection_to_tcomms()
if(node && node.on)
return can_telecomm(src,node)
return 0
/obj/item/integrated_circuit/input/EPv2/New()
..()
exonet = new(src)
exonet.make_address("EPv2_circuit-\ref[src]")
desc += "<br>This circuit's EPv2 address is: [exonet.address]"
node = get_exonet_node()
/obj/item/integrated_circuit/input/EPv2/Destroy()
if(exonet)
@@ -461,7 +468,15 @@
var/text = get_pin_data(IC_INPUT, 3)
if(target_address && istext(target_address))
exonet.send_message(target_address, message, text)
if(!get_connection_to_tcomms())
set_pin_data(IC_OUTPUT, 1, null)
set_pin_data(IC_OUTPUT, 2, "Error: Cannot connect to Exonet node.")
set_pin_data(IC_OUTPUT, 3, "error")
push_data()
activate_pin(2)
else
exonet.send_message(target_address, message, text)
/obj/item/integrated_circuit/input/receive_exonet_message(var/atom/origin_atom, var/origin_address, var/message, var/text)
set_pin_data(IC_OUTPUT, 1, origin_address)
@@ -263,15 +263,28 @@
/obj/item/integrated_circuit/output/video_camera
name = "video camera circuit"
desc = "This small camera allows a remote viewer to see what it sees."
extended_desc = "The camera is linked to the Research camera network."
var/list/networks = list(
"research" = NETWORK_CIRCUITS,
"engine" = NETWORK_ENGINE,
"engineering" = NETWORK_ENGINEERING,
"mining" = NETWORK_MINE,
"medical" = NETWORK_MEDICAL,
"entertainment" = NETWORK_THUNDER,
"security" = NETWORK_SECURITY,
"command" = NETWORK_COMMAND
)
icon_state = "video_camera"
w_class = ITEMSIZE_SMALL
complexity = 10
inputs = list(
"camera name" = IC_PINTYPE_STRING,
"camera network" = IC_PINTYPE_STRING,
"camera active" = IC_PINTYPE_BOOLEAN
)
inputs_default = list("1" = "video camera circuit")
inputs_default = list(
"1" = "video camera circuit",
"2" = "research"
)
outputs = list()
activators = list()
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
@@ -280,6 +293,11 @@
/obj/item/integrated_circuit/output/video_camera/New()
..()
extended_desc = list()
extended_desc += "Network choices are; "
extended_desc += jointext(networks, ", ")
extended_desc += "."
extended_desc = jointext(extended_desc, null)
camera = new(src)
on_data_written()
@@ -298,10 +316,20 @@
/obj/item/integrated_circuit/output/video_camera/on_data_written()
if(camera)
var/cam_name = get_pin_data(IC_INPUT, 1)
var/cam_active = get_pin_data(IC_INPUT, 2)
var/cam_network = get_pin_data(IC_INPUT, 2)
var/cam_active = get_pin_data(IC_INPUT, 3)
if(!isnull(cam_name))
camera.c_tag = cam_name
camera.replace_networks(list(cam_network))
set_camera_status(cam_active)
if(isnull(cam_network))
camera.clear_all_networks()
return
var/selected_network = networks[cam_network]
if(!selected_network)
camera.clear_all_networks()
return
camera.replace_networks(list(selected_network))
/obj/item/integrated_circuit/output/video_camera/power_fail()
if(camera)
@@ -13,7 +13,7 @@
hardness = 5
/datum/material/cloth/generate_recipes()
/datum/material/cloth/generate_recipes() //Vorestation Add - adding some funny cool storage pouches to this so botany can do things other than food
recipes = list(
new /datum/stack_recipe("woven net", /obj/item/weapon/material/fishing_net, 10, time = 30 SECONDS, pass_stack_color = TRUE, supplied_material = "[name]"),
new /datum/stack_recipe("bedsheet", /obj/item/weapon/bedsheet, 10, time = 30 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]"),
@@ -29,6 +29,13 @@
new /datum/stack_recipe("scarf", /obj/item/clothing/accessory/scarf/white, 4, time = 5 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("baggy pants", /obj/item/clothing/under/pants/baggy/white, 8, time = 10 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("belt pouch", /obj/item/weapon/storage/belt/fannypack/white, 25, time = 1 MINUTE, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("pouch, small", /obj/item/weapon/storage/pouch/small, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("pouch, ammo", /obj/item/weapon/storage/pouch/ammo, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("pouch, tools", /obj/item/weapon/storage/pouch/eng_tool, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("pouch, parts", /obj/item/weapon/storage/pouch/eng_parts, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("pouch, supplies", /obj/item/weapon/storage/pouch/eng_supply, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("pouch, medical", /obj/item/weapon/storage/pouch/medical, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("pouch, flare", /obj/item/weapon/storage/pouch/flares, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("crude bandage", /obj/item/stack/medical/crude_pack, 1, time = 2 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("empty sandbag", /obj/item/stack/emptysandbag, 2, time = 2 SECONDS, pass_stack_color = TRUE, supplied_material = "[name]"),
new /datum/stack_recipe("painting canvas (11x11)", /obj/item/canvas, 2, time = 2 SECONDS, pass_stack_color = FALSE, supplied_material = "[name]"),
@@ -27,6 +27,10 @@
new /datum/stack_recipe("scarf", /obj/item/clothing/accessory/scarf/white, 4, time = 5 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("baggy pants", /obj/item/clothing/under/pants/baggy/white, 8, time = 10 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("belt pouch", /obj/item/weapon/storage/belt/fannypack/white, 25, time = 1 MINUTE, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("pouch, medium", /obj/item/weapon/storage/pouch, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("pouch, large", /obj/item/weapon/storage/pouch/large, 15, time = 30 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("pouch, holster", /obj/item/weapon/storage/pouch/holster, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("pouch, melee", /obj/item/weapon/storage/pouch/baton, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("crude [display_name] bandage", /obj/item/stack/medical/crude_pack, 1, time = 2 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("[display_name] net", /obj/item/weapon/material/fishing_net, 10, time = 5 SECONDS, supplied_material = "[name]", pass_stack_color = TRUE),
new /datum/stack_recipe("[display_name] ring", /obj/item/clothing/gloves/ring/material, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE),
@@ -73,6 +73,13 @@
new /datum/stack_recipe("scarf", /obj/item/clothing/accessory/scarf/white/craftable, 4, time = 5 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("baggy pants", /obj/item/clothing/under/pants/baggy/white/craftable, 8, time = 10 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("belt pouch", /obj/item/weapon/storage/belt/fannypack/white/craftable, 25, time = 1 MINUTE, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("pouch, small", /obj/item/weapon/storage/pouch/small, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("pouch, ammo", /obj/item/weapon/storage/pouch/ammo, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("pouch, tools", /obj/item/weapon/storage/pouch/eng_tool, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("pouch, parts", /obj/item/weapon/storage/pouch/eng_parts, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("pouch, supplies", /obj/item/weapon/storage/pouch/eng_supply, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("pouch, medical", /obj/item/weapon/storage/pouch/medical, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("pouch, flare", /obj/item/weapon/storage/pouch/flares, 10, time = 20 SECONDS, pass_stack_color = FALSE, recycle_material = "[name]"), //vorestation Add
new /datum/stack_recipe("crude bandage", /obj/item/stack/medical/crude_pack, 1, time = 2 SECONDS, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("empty sandbag", /obj/item/stack/emptysandbag, 2, time = 2 SECONDS, pass_stack_color = TRUE, supplied_material = "[name]"),
new /datum/stack_recipe("satchel", /obj/item/weapon/storage/backpack/satchel/craftable, 30, time = 1 MINUTE, pass_stack_color = TRUE, recycle_material = "[name]"),
+6 -1
View File
@@ -230,7 +230,7 @@
desc = "A modified design of a proto-kinetic crusher, it is still little more of a combination of various mining tools cobbled together \
and kit-bashed into a high-tech cleaver on a stick - with a handguard and a goliath hide grip. While it is still of little use to any \
but the most skilled and/or suicidal miners against local fauna, it's an elegant weapon for a more civilized hunter."
look gary there i am
- hatterhat
*/
@@ -256,6 +256,9 @@
backstab_bonus = 40 // 100
thrown_bonus = 20 // 120
update_item_state = FALSE
slot_flags = SLOT_BELT
/obj/item/weapon/kinetic_crusher/machete/gauntlets
@@ -275,6 +278,7 @@
detonation_damage = 37 // 75
backstab_bonus = 55 // 130
var/obj/item/offhand/crushergauntlets/offhand
slot_flags = null
/obj/item/weapon/kinetic_crusher/machete/gauntlets/equipped()
. = ..()
@@ -381,6 +385,7 @@
thrown_bonus = 50 // 135 but you drop your knife because you threw it
//destablizing force
/obj/item/projectile/destabilizer
name = "destabilizing force"
+14 -9
View File
@@ -27,11 +27,14 @@
if(always_stars)
piece = stars(piece)
else if(!say_understands(speaker, SP.speaking))
piece = saypiece_scramble(SP)
if(isliving(speaker))
var/mob/living/S = speaker
if(istype(S.say_list) && length(S.say_list.speak))
piece = pick(S.say_list.speak)
if(SP.speaking.flags & INAUDIBLE)
piece = ""
else
piece = saypiece_scramble(SP)
if(isliving(speaker))
var/mob/living/S = speaker
if(istype(S.say_list) && length(S.say_list.speak))
piece = pick(S.say_list.speak)
raw_msg += (piece + " ")
@@ -226,13 +229,13 @@
final_message = "[time][final_message]"
to_chat(src, final_message)
/mob/proc/hear_signlang(var/message, var/verb = "gestures", var/datum/language/language, var/mob/speaker = null)
/mob/proc/hear_signlang(var/message, var/verb = "gestures", var/verb_understood = "gestures", var/datum/language/language, var/mob/speaker = null, var/speech_type = 1)
if(!client)
return
if(say_understands(speaker, language))
message = "<B>[speaker]</B> [verb], \"[message]\""
else
message = "<B>[speaker]</B> [verb_understood], \"[message]\""
else if(!(language.ignore_adverb))
var/adverb
var/length = length(message) * pick(0.8, 0.9, 1.0, 1.1, 1.2) //Adds a little bit of fuzziness
switch(length)
@@ -242,8 +245,10 @@
if(48 to 90) adverb = " a lengthy message"
else adverb = " a very lengthy message"
message = "<B>[speaker]</B> [verb][adverb]."
else
message = "<B>[speaker]</B> [verb]."
show_message(message, type = 1) // Type 1 is visual message
show_message(message, type = speech_type) // Type 1 is visual message
/mob/proc/hear_sleep(var/message)
var/heard = ""
+3 -2
View File
@@ -145,8 +145,9 @@
// which is exactly what sign language does.
/datum/language/sign/broadcast(var/mob/living/speaker, var/message, var/speaker_mask)
log_say("(SIGN) [message]", speaker)
speaker.say_signlang(message, pick(signlang_verb), src)
var/verb_to_use = pick(signlang_verb)
speaker.say_signlang(message, verb_to_use, verb_to_use, src)
// Silly language for those times when you try to talk a languague you normally can't
/datum/language/gibberish
+3 -1
View File
@@ -12,6 +12,7 @@
var/exclaim_verb = "exclaims" // Used when sentence ends in a !
var/whisper_verb // Optional. When not specified speech_verb + quietly/softly is used instead.
var/signlang_verb = list("signs", "gestures") // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags
var/signlang_verb_understood = list("signs") // snowflake bs, used only for echo
var/colour = "body" // CSS style to use for strings in this language.
var/key = "x" // Character used to speak in language eg. :o for Unathi.
var/flags = 0 // Various language flags.
@@ -20,6 +21,7 @@
var/list/space_chance = 55 // Likelihood of getting a space in the random scramble string
var/machine_understands = 1 // Whether machines can parse and understand this language
var/list/partial_understanding // List of languages that can /somehwat/ understand it, format is: name = chance of understanding a word
var/ignore_adverb = FALSE // For inaudible languages that we dont want adverb for
/datum/language/proc/get_random_name(var/gender, name_count=2, syllable_count=4, syllable_divisor=2)
if(!syllables || !syllables.len)
@@ -235,7 +237,7 @@
//TBD
/mob/proc/check_lang_data()
. = ""
for(var/datum/language/L in languages)
if(!(L.flags & NONGLOBAL))
. += "<b>[L.name] ([get_language_prefix()][L.key])</b><br/>[L.desc]<br/><br/>"
+2 -1
View File
@@ -96,7 +96,8 @@
/datum/language/tajsign/broadcast(var/mob/living/speaker, var/message, var/speaker_mask)
log_say("(SIGN) [message]", speaker)
speaker.say_signlang(message, pick(signlang_verb), src)
var/verb_to_use = pick(signlang_verb)
speaker.say_signlang(message, verb_to_use, verb_to_use, src)
/datum/language/tajsign/can_speak_special(var/mob/speaker) // TODO: If ever we make external organs assist languages, convert this over to the new format
var/list/allowed_species = list(SPECIES_TAJ, SPECIES_TESHARI) // Need a tail and ears and such to use this.
+18 -1
View File
@@ -167,7 +167,24 @@
exclaim_verb = "squeaks loudly"
syllables = list ("sque", "uik", "squeak", "squee", "eak", "eek", "uek", "squik",
"squeek", "sq", "squee", "ee", "ek", "ak", "ueak", "squea")
colour = "tavan"
colour = "tavan"
/datum/language/echosong
name = LANGUAGE_ECHOSONG
desc = "An ultrasound-based language, inaudible to those unable to understand it."
key = "U"
signlang_verb = list("opens their mouth soundlessly", "mouthes something silently")
signlang_verb_understood = list("squeaks")
colour = "echosong"
flags = INAUDIBLE
ignore_adverb = TRUE
/datum/language/echosong/scramble(var/input, var/list/known_languages)
return stars(input)
/datum/language/echosong/broadcast(var/mob/living/speaker, var/message, var/speaker_mask)
log_say("(INAUDIBLE) [message]", speaker)
speaker.say_signlang(format_message(message), pick(signlang_verb), pick(signlang_verb_understood), src, 2)
/datum/language/unathi
flags = 0
+26 -1
View File
@@ -53,8 +53,33 @@
autohiss_basic_map = list(
"r" = list("rr", "rrr", "rrrr")
)
autohiss_exempt = list(LANGUAGE_SIIK,LANGUAGE_AKHANI)
autohiss_exempt = list(LANGUAGE_SIIK,LANGUAGE_AKHANI,LANGUAGE_ALAI)
/datum/species/zaddat
autohiss_basic_map = list(
"f" = list("v","vh"),
"ph" = list("v", "vh")
)
autohiss_extra_map = list(
"s" = list("z", "zz", "zzz"),
"ce" = list("z", "zz"),
"ci" = list("z", "zz"),
"v" = list("vv", "vvv")
)
autohiss_exempt = list(LANGUAGE_ZADDAT,LANGUAGE_VESPINAE)
/datum/species/zaddat
autohiss_basic_map = list(
"f" = list("v","vh"),
"ph" = list("v", "vh")
)
autohiss_extra_map = list(
"s" = list("z", "zz", "zzz"),
"ce" = list("z", "zz"),
"ci" = list("z", "zz"),
"v" = list("vv", "vvv")
)
autohiss_exempt = list(LANGUAGE_ZADDAT)
//Yawn Wider Edit.
/datum/species/spider
+108 -3
View File
@@ -17,7 +17,7 @@
var/emagged = 0
var/light_strength = 3
var/busy = 0
var/obj/item/device/paicard/paicard = null
var/obj/access_scanner = null
var/list/req_access = list()
var/list/req_one_access = list()
@@ -73,10 +73,27 @@
SetStunned(0)
SetParalysis(0)
if(on && !client && !busy)
if(on && !client && !busy && !paicard)
spawn(0)
handleAI()
/*
/mob/living/bot/examine(mob/user)
. = ..()
if(health < maxHealth)
if(health > maxHealth/3)
. += "[src]'s parts look loose."
else
. += "[src]'s parts look very loose!"
else
. += "[src] is in pristine condition."
. += span_notice("Its maintenance panel is [open ? "open" : "closed"].")
. += span_info("You can use a <b>screwdriver</b> to [open ? "close" : "open"] it.")
. += span_notice("Its control panel is [locked ? "locked" : "unlocked"].")
if(paicard)
. += span_notice("It has a pAI device installed.")
if(open)
. += span_info("You can use a <b>crowbar</b> to remove it.")
*/
/mob/living/bot/updatehealth()
if(status_flags & GODMODE)
health = getMaxHealth()
@@ -139,6 +156,17 @@
qdel(O)
else
to_chat(user, "<span class='notice'>Unable to repair with the maintenance panel closed.</span>")
else if(istype(O, /obj/item/device/paicard))
if(open)
insertpai(user, O)
to_chat(user, span_notice("You slot the card into \the [initial(src.name)]."))
else
to_chat(user, span_notice("You must open the panel first!"))
else if(O.is_crowbar())
if(open && paicard)
to_chat(user, span_notice("You are attempting to remove the pAI.."))
if(do_after(user,10 * O.toolspeed))
ejectpai(user)
else
..()
@@ -212,6 +240,13 @@
if(LAZYLEN(can_go))
if(step_towards(src, pick(can_go)))
return
for(var/mob in loc)
if(istype(mob, /mob/living/bot) && mob != src) // Same as above, but we also don't want to have bots ontop of bots. Cleanbots shouldn't stack >:(
var/turf/my_turf = get_turf(src)
var/list/can_go = my_turf.CardinalTurfsWithAccess(botcard)
if(LAZYLEN(can_go))
if(step_towards(src, pick(can_go)))
return
handleIdle()
/mob/living/bot/proc/handleRegular()
@@ -367,9 +402,14 @@
update_icons()
/mob/living/bot/proc/explode()
if(paicard)
ejectpai()
release_vore_contents()
qdel(src)
/mob/living/bot/is_sentient()
if(paicard)
return TRUE
return FALSE
/******************************************************************/
@@ -458,3 +498,68 @@
/mob/living/bot/isSynthetic() //Robots are synthetic, no?
return 1
/mob/living/bot/proc/insertpai(mob/user, obj/item/device/paicard/card)
//var/obj/item/paicard/card = I
var/mob/living/silicon/pai/AI = card.pai
if(paicard)
to_chat(user, span_notice("This bot is already under PAI Control!"))
return
if(!istype(card)) // TODO: Add sleevecard support.
return
if(client)
to_chat(user, span_notice("Higher levels of processing are already present!"))
return
if(!card.pai)
to_chat(user, span_notice("This card does not currently have a personality!"))
return
paicard = card
user.unEquip(card)
card.forceMove(src)
src.ckey = AI.ckey
name = AI.name
ooc_notes = AI.ooc_notes
to_chat(src, span_notice("You feel a tingle in your circuits as your systems interface with \the [initial(src.name)]."))
if(AI.idcard.access)
botcard.access |= AI.idcard.access
/mob/living/bot/proc/ejectpai(mob/user)
if(paicard)
var/mob/living/silicon/pai/AI = paicard.pai
AI.ckey = src.ckey
AI.ooc_notes = ooc_notes
paicard.forceMove(src.loc)
paicard = null
name = initial(name)
botcard.access = botcard_access.Copy()
to_chat(AI, span_notice("You feel a tad claustrophobic as your mind closes back into your card, ejecting from \the [initial(src.name)]."))
if(user)
to_chat(user, span_notice("You eject the card from \the [initial(src.name)]."))
/mob/living/bot/verb/bot_nom(var/mob/living/T in oview(1))
set name = "Bot Nom"
set category = "Bot Commands"
set desc = "Allows you to eat someone. Yum."
if (stat != CONSCIOUS)
return
return feed_grabbed_to_self(src,T)
/mob/living/bot/verb/ejectself()
set name = "Eject pAI"
set category = "Bot Commands"
set desc = "Eject your card, return to smole."
return ejectpai()
/mob/living/bot/Login()
no_vore = FALSE // ROBOT VORE
init_vore() // ROBOT VORE
verbs |= /mob/living/proc/insidePanel
/mob/living/bot/Logout()
no_vore = TRUE // ROBOT VORE
release_vore_contents()
init_vore() // ROBOT VORE
verbs -= /mob/living/proc/insidePanel
+2 -2
View File
@@ -141,8 +141,8 @@
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
qdel(src)
return
//qdel(src)
return ..()
/mob/living/bot/cleanbot/update_icons()
if(busy)
+1 -1
View File
@@ -49,7 +49,7 @@
s.start()
new /obj/effect/decal/cleanable/blood/oil(Tsec)
qdel(src)
return ..()
/mob/living/bot/secbot/ed209/handleRangedTarget()
RangedAttack(target)
+2 -2
View File
@@ -68,8 +68,8 @@
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
qdel(src)
return
//qdel(src)
return ..()
/mob/living/bot/cleanbot/edCLN/tgui_data(mob/user)
var/list/data = ..()
+2 -2
View File
@@ -286,8 +286,8 @@
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
qdel(src)
return
//qdel(src)
return ..()
/mob/living/bot/farmbot/confirmTarget(var/atom/targ)
+5 -4
View File
@@ -42,7 +42,7 @@
data["on"] = on
data["open"] = open
data["locked"] = locked
data["vocal"] = vocal
data["amount"] = amount
@@ -75,7 +75,7 @@
/mob/living/bot/floorbot/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
add_fingerprint(src)
switch(action)
@@ -85,7 +85,7 @@
else
turn_on()
. = TRUE
if(locked && !issilicon(usr))
return
@@ -302,7 +302,8 @@
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
qdel(src)
//qdel(src)
return ..()
/mob/living/bot/floorbot/proc/addTiles(var/am)
amount += am
+4 -4
View File
@@ -269,10 +269,10 @@
/mob/living/bot/medbot/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
usr.set_machine(src)
add_fingerprint(usr)
. = TRUE
switch(action)
if("power")
@@ -349,8 +349,8 @@
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
qdel(src)
return
//qdel(src)
return ..()
/mob/living/bot/medbot/handleRegular()
. = ..()
+3 -2
View File
@@ -129,7 +129,7 @@
/mob/living/bot/secbot/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return
add_fingerprint(usr)
switch(action)
@@ -380,7 +380,8 @@
s.start()
new /obj/effect/decal/cleanable/blood/oil(Tsec)
qdel(src)
//qdel(src)
return ..()
/mob/living/bot/secbot/proc/target_name(mob/living/T)
if(ishuman(T))
@@ -323,7 +323,7 @@ emp_act
if(!stat)
switch(hit_zone)
if("head")//Harder to score a stun but if you do it lasts a bit longer
if(BP_HEAD)//Harder to score a stun but if you do it lasts a bit longer
if(prob(effective_force))
apply_effect(20, PARALYZE, blocked, soaked)
visible_message("<span class='danger'>\The [src] has been knocked unconscious!</span>")
@@ -337,7 +337,7 @@ emp_act
if(glasses && prob(33))
glasses.add_blood(src)
update_inv_glasses(0)
if("chest")//Easier to score a stun but lasts less time
if(BP_TORSO)//Easier to score a stun but lasts less time
if(prob(effective_force + 10))
apply_effect(6, WEAKEN, blocked, soaked)
visible_message("<span class='danger'>\The [src] has been knocked down!</span>")
@@ -53,8 +53,8 @@
autohiss_extra_map = list(
"x" = list("ks", "kss", "ksss")
),
autohiss_exempt = list("Sinta'unathi"))
excludes = list(/datum/trait/neutral/autohiss_tajaran, /datum/trait/neutral/autohiss_vassilian) // CHOMPEdit: exclude vassillian hiss
autohiss_exempt = list(LANGUAGE_UNATHI))
excludes = list(/datum/trait/neutral/autohiss_tajaran, /datum/trait/neutral/autohiss_vassilian, /datum/trait/neutral/autohiss_zaddat) // CHOMPEdit: exclude vassillian hiss
/datum/trait/neutral/autohiss_tajaran
name = "Autohiss (Tajaran)"
@@ -64,8 +64,26 @@
autohiss_basic_map = list(
"r" = list("rr", "rrr", "rrrr")
),
autohiss_exempt = list("Siik"))
excludes = list(/datum/trait/neutral/autohiss_unathi, /datum/trait/neutral/autohiss_vassilian) // CHOMPEdit: exclude vassillian hiss
autohiss_exempt = list(LANGUAGE_SIIK,LANGUAGE_AKHANI,LANGUAGE_ALAI))
excludes = list(/datum/trait/neutral/autohiss_unathi, /datum/trait/neutral/autohiss_zaddat, /datum/trait/neutral/autohiss_vassilian) // CHOMPEdit: exclude vassillian hiss
/datum/trait/neutral/autohiss_zaddat
name = "Autohiss (Zaddat)"
desc = "You buzz your S's and F's."
cost = 0
var_changes = list(
autohiss_basic_map = list(
"f" = list("v","vh"),
"ph" = list("v", "vh")
),
autohiss_extra_map = list(
"s" = list("z", "zz", "zzz"),
"ce" = list("z", "zz"),
"ci" = list("z", "zz"),
"v" = list("vv", "vvv")
),
autohiss_exempt = list(LANGUAGE_ZADDAT,LANGUAGE_VESPINAE))
excludes = list(/datum/trait/neutral/autohiss_tajaran, /datum/trait/neutral/autohiss_unathi)
/datum/trait/neutral/bloodsucker
name = "Bloodsucker, Obligate"
@@ -514,3 +532,13 @@
/datum/trait/neutral/submit_to_prey/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..(S,H)
H.verbs |= /mob/living/proc/lend_prey_control
/datum/trait/neutral/vertical_nom
name = "Vertical Nom"
desc = "Allows you to consume people from up above."
cost = 0
custom_only = FALSE
/datum/trait/neutral/vertical_nom/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..(S,H)
H.verbs |= /mob/living/proc/vertical_nom
@@ -60,19 +60,19 @@
var_changes = list("darksight" = 6) //CHOMP Edit
*/
/datum/trait/positive/melee_attack
name = "Special Attack: Sharp Melee" // CHOMPEdit: Trait Organization for easier browsing. TODO: Proper categorization of 'health/ability/resist/etc'
name = "Special Attack: Sharp Melee" // Trait Organization for easier browsing. TODO: Proper categorization of 'health/ability/resist/etc'
desc = "Provides sharp melee attacks that do slightly more damage."
cost = 1
var_changes = list("unarmed_types" = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws, /datum/unarmed_attack/bite/sharp))
/datum/trait/positive/melee_attack_fangs
name = "Special Attack: Sharp Melee & Numbing Fangs" // CHOMPEdit: Trait Organization for easier browsing. TODO: Proper categorization of 'health/ability/resist/etc'
name = "Special Attack: Sharp Melee & Numbing Fangs" // Trait Organization for easier browsing. TODO: Proper categorization of 'health/ability/resist/etc'
desc = "Provides sharp melee attacks that do slightly more damage, along with fangs that makes the person bit unable to feel their body or pain."
cost = 2
var_changes = list("unarmed_types" = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws, /datum/unarmed_attack/bite/sharp, /datum/unarmed_attack/bite/sharp/numbing))
/datum/trait/positive/fangs
name = "Special Attack: Numbing Fangs" // CHOMPEdit: Trait Organization for easier browsing. TODO: Proper categorization of 'health/ability/resist/etc'
name = "Special Attack: Numbing Fangs" // Trait Organization for easier browsing. TODO: Proper categorization of 'health/ability/resist/etc'
desc = "Provides fangs that makes the person bit unable to feel their body or pain."
cost = 1
var_changes = list("unarmed_types" = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch, /datum/unarmed_attack/bite/sharp/numbing))
+14 -3
View File
@@ -79,12 +79,23 @@
return 1
/mob/living/verb/succumb()
set hidden = 1
if ((src.health < 0 && src.health > (5-src.getMaxHealth()))) // Health below Zero but above 5-away-from-death, as before, but variable
set name = "Succumb to death"
set category = "IC"
set desc = "Press this button if you are in crit and wish to die. Use this sparingly (ending a scene, no medical, etc.)"
var/confirm1 = tgui_alert(usr, "Pressing this button will kill you instantenously! Are you sure you wish to proceed?", "Confirm wish to succumb", list("No","Yes"))
var/confirm2 = "No"
if(confirm1 == "Yes")
confirm2 = tgui_alert(usr, "Pressing this buttom will really kill you, no going back", "Are you sure?", list("Yes", "No")) //Swapped answers to protect from accidental double clicks.
if (src.health < 0 && stat != DEAD && confirm1 == "Yes" && confirm2 == "Yes") // Checking both confirm1 and confirm2 for good measure. I don't trust TGUI.
src.death()
to_chat(src, "<font color='blue'>You have given up life and succumbed to death.</font>")
else
to_chat(src, "<font color='blue'>You are not injured enough to succumb to death!</font>")
if(stat == DEAD)
to_chat(src, "<font color='blue'>As much as you'd like, you can't die when already dead</font>")
else if(confirm1 == "No" || confirm2 == "No")
to_chat(src, "<font color='blue'>You chose to live another day.</font>")
else
to_chat(src, "<font color='blue'>You are not injured enough to succumb to death!</font>")
/mob/living/proc/updatehealth()
if(status_flags & GODMODE)
+16 -4
View File
@@ -300,7 +300,7 @@ var/list/channel_to_radio_key = new
//Handle nonverbal languages here
for(var/datum/multilingual_say_piece/S in message_pieces)
if(S.speaking.flags & NONVERBAL)
if((S.speaking.flags & NONVERBAL) || (S.speaking.flags & INAUDIBLE))
custom_emote(1, "[pick(S.speaking.signlang_verb)].")
//These will contain the main receivers of the message
@@ -407,21 +407,33 @@ var/list/channel_to_radio_key = new
log_say(message, src)
return 1
/mob/living/proc/say_signlang(var/message, var/verb="gestures", var/datum/language/language)
/mob/living/proc/say_signlang(var/message, var/verb="gestures", var/verb_understood="gestures", var/datum/language/language, var/type = 1)
var/turf/T = get_turf(src)
//We're in something, gesture to people inside the same thing
if(loc != T)
for(var/mob/M in loc)
M.hear_signlang(message, verb, language, src)
M.hear_signlang(message, verb, verb_understood, language, src, type)
//We're on a turf, gesture to visible as if we were a normal language
else
var/low_range = FALSE
if(T && type == 2) // type 2 is audible signlang. yes. sue me.
//Air is too thin to carry sound at all, contact speech only
var/datum/gas_mixture/environment = T.return_air()
var/pressure = environment ? environment.return_pressure() : 0
if(pressure < SOUND_MINIMUM_PRESSURE)
low_range = TRUE
var/list/potentials = get_mobs_and_objs_in_view_fast(T, world.view)
var/list/mobs = potentials["mobs"]
for(var/mob/M as anything in mobs)
M.hear_signlang(message, verb, language, src)
if(low_range && !(M in range(1, src)))
continue
M.hear_signlang(message, verb, verb_understood, language, src, type)
var/list/objs = potentials["objs"]
for(var/obj/O as anything in objs)
if(low_range && !(O in range(1, src)))
continue
O.hear_signlang(message, verb, language, src)
return 1
@@ -247,6 +247,9 @@
last_special = world.time + 100
if(istype(card.loc, /obj/machinery)) // VOREStation edit, this statement allows pAIs stuck in a machine to eject themselves.
var/obj/machinery/M = card.loc
M.ejectpai()
//I'm not sure how much of this is necessary, but I would rather avoid issues.
if(istype(card.loc,/obj/item/rig_module))
to_chat(src, "There is no room to unfold inside this rig module. You're good and stuck.")
@@ -72,9 +72,86 @@
// For really persistent looters
src.emag = new /obj/item/weapon/gun/energy/retro/mounted(src)
var/datum/matter_synth/wood = new /datum/matter_synth/wood(25000)
var/datum/matter_synth/wood = new /datum/matter_synth/wood(50000) //CHOMPEdit - "Buffing this to 50k on account of broken code not letting us pick up more stacks. Wee."
synths += wood
var/obj/item/stack/material/cyborg/wood/W = new (src)
W.synths = list(wood)
src.modules += W
src.modules += W
//CHOMPEdit - "Giving the gravekeeper drone more modules to allow it to actually do it's job."
src.modules += new /obj/item/weapon/tool/wirecutters/cyborg(src) //Gotta clear those pesky landmines somehow. Also allows for deconstruction of things in the way!
src.modules += new /obj/item/device/multitool(src)
src.modules += new /obj/item/device/lightreplacer(src)
src.modules += new /obj/item/weapon/gripper/no_use/loader(src)
src.modules += new /obj/item/weapon/gripper(src)
src.modules += new /obj/item/weapon/pickaxe(src)
src.modules += new /obj/item/device/floor_painter(src)
src.modules += new /obj/item/weapon/pen/robopen(src)
src.modules += new /obj/item/weapon/form_printer(src)
src.modules += new /obj/item/weapon/gripper/paperwork(src)
src.modules += new /obj/item/weapon/hand_labeler(src)
src.modules += new /obj/item/weapon/stamp(src)
src.modules += new /obj/item/weapon/stamp/denied(src)
var/obj/item/weapon/flame/lighter/zippo/L = new /obj/item/weapon/flame/lighter/zippo(src)
L.lit = 1
src.modules += L
src.emag = new /obj/item/weapon/stamp/chameleon(src)
src.emag = new /obj/item/weapon/pen/chameleon(src)
var/datum/matter_synth/metal = new /datum/matter_synth/metal(50000)
var/datum/matter_synth/glass = new /datum/matter_synth/glass(50000)
var/datum/matter_synth/plasteel = new /datum/matter_synth/plasteel(20000)
var/datum/matter_synth/plastic = new /datum/matter_synth/plastic(50000)
var/datum/matter_synth/wire = new /datum/matter_synth/wire()
synths += metal
synths += glass
synths += plasteel
synths += plastic
synths += wire
var/obj/item/weapon/matter_decompiler/MD = new /obj/item/weapon/matter_decompiler(src)
MD.metal = metal
MD.glass = glass
src.modules += MD
var/obj/item/stack/material/cyborg/steel/M = new (src)
M.synths = list(metal)
src.modules += M
var/obj/item/stack/material/cyborg/glass/G = new (src)
G.synths = list(glass)
src.modules += G
var/obj/item/stack/rods/cyborg/rods = new /obj/item/stack/rods/cyborg(src)
rods.synths = list(metal)
src.modules += rods
var/obj/item/stack/cable_coil/cyborg/C = new /obj/item/stack/cable_coil/cyborg(src)
C.synths = list(wire)
src.modules += C
var/obj/item/stack/material/cyborg/plasteel/PS = new (src)
PS.synths = list(plasteel)
src.modules += PS
var/obj/item/stack/tile/wood/cyborg/WT = new /obj/item/stack/tile/wood/cyborg(src)
WT.synths = list(wood)
src.modules += WT
var/obj/item/stack/tile/floor/cyborg/S = new /obj/item/stack/tile/floor/cyborg(src)
S.synths = list(metal)
src.modules += S
var/obj/item/stack/tile/roofing/cyborg/CT = new /obj/item/stack/tile/roofing/cyborg(src)
CT.synths = list(metal)
src.modules += CT
var/obj/item/stack/material/cyborg/glass/reinforced/RG = new (src)
RG.synths = list(metal, glass)
src.modules += RG
var/obj/item/stack/material/cyborg/plastic/PL = new (src)
PL.synths = list(plastic)
src.modules += PL //CHOMEdit End
@@ -4,6 +4,7 @@
real_name = "cockroach"
desc = "This station is just crawling with bugs."
tt_desc = "E Blattella germanica"
icon = 'icons/mob/animal_vr.dmi'
icon_state = "cockroach"
item_state = "cockroach"
icon_living = "cockroach"
@@ -12,6 +12,16 @@
return
/mob/living/simple_mob/animal/passive/lizard/event/proc/man()
visible_message("<span class='warning'>\The [src] suddenly evolves!</span>")
new /mob/living/simple_mob/vore/aggressive/lizardman(get_turf(src))
qdel(src)
var/mob/bigger = new /mob/living/simple_mob/vore/aggressive/lizardman(get_turf(src))
if(istype(loc,/obj/belly)){
var/obj/belly/B = loc
B.owner.visible_message("<span class='warning'><b>Something grows inside [B.owner]'s [lowertext(B.name)]!</b></span>")
to_chat(B.owner, "<span class='warning'>\The [src] suddenly evolves inside your [lowertext(B.name)]!</span>")
B.release_specific_contents(src, TRUE)
B.nom_mob(bigger, null)
qdel(src)
}else{
visible_message("<span class='warning'>\The [src] suddenly evolves!</span>")
qdel(src)
}
@@ -11,9 +11,20 @@
return
/mob/living/simple_mob/animal/passive/mouse/event/proc/rat()
visible_message("<span class='warning'>\The [src] suddenly evolves!</span>")
var/mob/bigger = null
if(prob(99.5))
new /mob/living/simple_mob/vore/aggressive/rat/event(get_turf(src))
qdel(src)
bigger = new /mob/living/simple_mob/vore/aggressive/rat/event(get_turf(src))
else
new /mob/living/simple_mob/vore/aggressive/chungus(get_turf(src))
bigger = new /mob/living/simple_mob/vore/aggressive/chungus(get_turf(src))
if(istype(loc,/obj/belly)){
var/obj/belly/B = loc
B.owner.visible_message("<span class='warning'><b>Something grows inside [B.owner]'s [lowertext(B.name)]!</b></span>")
to_chat(B.owner, "<span class='warning'>\The [src] suddenly evolves inside your [lowertext(B.name)]!</span>")
B.release_specific_contents(src, TRUE)
B.nom_mob(bigger, null)
qdel(src)
}else{
visible_message("<span class='warning'>\The [src] suddenly evolves!</span>")
qdel(src)
}
+25 -25
View File
@@ -604,34 +604,34 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HURT)
//The base miss chance for the different defence zones
var/list/global/base_miss_chance = list(
"head" = 40,
"torso" = 10,
"groin" = 20,
"l_leg" = 20,
"r_leg" = 20,
"l_arm" = 20,
"r_arm" = 20,
"l_hand" = 50,
"r_hand" = 50,
"l_foot" = 50,
"r_foot" = 50,
) //CHOMPEDIT - Changed "chest" to "torso", as chest is a typo. How long has this bug been here?
BP_HEAD = 40,
BP_TORSO = 10,
BP_GROIN = 20,
BP_L_LEG = 20,
BP_R_LEG = 20,
BP_L_ARM = 20,
BP_R_ARM = 20,
BP_L_HAND = 50,
BP_R_HAND = 50,
BP_L_FOOT = 50,
BP_R_FOOT = 50,
)
//Used to weight organs when an organ is hit randomly (i.e. not a directed, aimed attack).
//Also used to weight the protection value that armour provides for covering that body part when calculating protection from full-body effects.
var/list/global/organ_rel_size = list(
"head" = 25,
"torso" = 70,
"groin" = 30,
"l_leg" = 25,
"r_leg" = 25,
"l_arm" = 25,
"r_arm" = 25,
"l_hand" = 10,
"r_hand" = 10,
"l_foot" = 10,
"r_foot" = 10,
) //CHOMPEDIT - Changed "chest" to "torso", as chest is a typo. How long has this bug been here?
BP_HEAD = 25,
BP_TORSO = 70,
BP_GROIN = 30,
BP_L_LEG = 25,
BP_R_LEG = 25,
BP_L_ARM = 25,
BP_R_ARM = 25,
BP_L_HAND = 10,
BP_R_HAND = 10,
BP_L_FOOT = 10,
BP_R_FOOT = 10,
)
/mob/proc/flash_eyes(intensity = FLASH_PROTECTION_MODERATE, override_blindness_check = FALSE, affect_silicon = FALSE, visual = FALSE, type = /obj/screen/fullscreen/flash)
return
@@ -689,4 +689,4 @@ var/global/image/backplane
item.screen_loc = screen_place
/mob/proc/can_feed()
return TRUE
return TRUE
@@ -135,6 +135,13 @@
extra_overlay = "naga_markings"
//icon_sprite_tag = "naga2c"
/datum/sprite_accessory/tail/taur/naga/alt_2c
name = "Naga alt style dual-color (Taur)"
suit_sprites = 'icons/mob/taursuits_naga_alt_vr.dmi'
icon_state = "altnaga_s"
extra_overlay = "altnaga_markings"
//icon_sprite_tag = "altnaga2c"
/datum/sprite_accessory/tail/taur/horse
name = "Horse (Taur)"
icon_state = "horse_s"
@@ -226,3 +226,12 @@
do_colouration = 1
color_blend_mode = ICON_MULTIPLY
extra_overlay = "drago_wing_2"
/datum/sprite_accessory/wing/aeromorph_flat
name = "aeromorph wings, flat"
desc = ""
icon_state = "aeromorph_flat"
do_colouration = 1
color_blend_mode = ICON_MULTIPLY
extra_overlay = "aeromorph_flat_1"
extra_overlay2 = "aeromorph_flat_2"
+1 -1
View File
@@ -249,7 +249,7 @@
// There are a few things that will make us want to ignore all other languages in - namely, HIVEMIND languages.
var/datum/language/L = current[1]
if(L && (L.flags & HIVEMIND || L.flags & SIGNLANG))
if(L && (L.flags & HIVEMIND || L.flags & SIGNLANG || L.flags & INAUDIBLE))
return new /datum/multilingual_say_piece(L, trim(sanitize(strip_prefixes(message))))
if(i + 1 > length(prefix_locations)) // We are out of lookaheads, that means the rest of the message is in cur lang
@@ -9,10 +9,12 @@
switch(network)
if(NETWORK_THUNDER)
return 0
if(NETWORK_ENGINE,NETWORK_ALARM_ATMOS,NETWORK_ALARM_FIRE,NETWORK_ALARM_POWER)
if(NETWORK_ENGINE,NETWORK_ENGINEERING,NETWORK_ALARM_ATMOS,NETWORK_ALARM_FIRE,NETWORK_ALARM_POWER)
return access_engine
if(NETWORK_CIRCUITS)
return access_research
if(NETWORK_MINE)
return access_qm
if(NETWORK_ERT)
return access_cent_specops
//VOREStation Add Start
+4
View File
@@ -77,12 +77,16 @@ var/const/CE_STABLE_THRESHOLD = 0.5
var/obj/item/organ/internal/heart/heart = internal_organs_by_name[O_HEART]
if(!heart)
blood_volume_raw = 0
blood_volume = 0
else if(heart.is_broken())
blood_volume_raw *= 0.3
blood_volume *= 0.3
else if(heart.is_bruised())
blood_volume_raw *= 0.7
blood_volume *= 0.7
else if(heart.damage)
blood_volume_raw *= 0.8
blood_volume *= 0.8
//Effects of bloodloss
+1
View File
@@ -384,5 +384,6 @@
/obj/item/device/toner
name = "toner cartridge"
icon = 'icons/obj/device.dmi'
icon_state = "tonercartridge"
var/toner_amount = 30
@@ -166,6 +166,7 @@
caliber = ".45 LC"
icon_state = "rifle-casing"
projectile_type = /obj/item/projectile/bullet/rifle/a45lc
matter = list(DEFAULT_WALL_MATERIAL = 169)
/obj/item/ammo_casing/a45lc/rifle
desc = "A long silver bullet... +P, and .45 LC stamped into the base."
@@ -173,4 +174,5 @@
/obj/item/ammo_casing/a45lc/rubber
desc = "A long silver bullet... Has a rubber tip, and .45 LC stamped into the base."
projectile_type = /obj/item/projectile/bullet/rifle/a45lc/rubber
projectile_type = /obj/item/projectile/bullet/rifle/a45lc/rubber
@@ -51,6 +51,13 @@
required_reagents = list("cordradaxon" = 1, "gastirodaxon" = 1, "hepanephrodaxon" = 1, "respirodaxon" = 1)
result_amount = 12 //More phoron-efficient alternative recipe.
/decl/chemical_reaction/instant/sorbitol
name = "Sorbitol"
id = "sorbitol"
result = "sorbitol"
required_reagents = list("unsorbitol" = 1, "phoron" = 1)
result_amount = 2
///SAP RECIPES//////
/decl/chemical_reaction/instant/myelamine_sap //This is the clotting agent used by clotting packs.
@@ -53,6 +53,30 @@
name = "vial (amorphorovir)"
prefill = list("amorphorovir" = 1)
/obj/item/weapon/reagent_containers/glass/beaker/vial/androrovir
name = "vial (androrovir)"
prefill = list("androrovir" = 1)
/obj/item/weapon/reagent_containers/glass/beaker/vial/gynorovir
name = "vial (gynorovir)"
prefill = list("gynorovir" = 1)
/obj/item/weapon/reagent_containers/glass/beaker/vial/androgynorovir
name = "vial (androgynorovir)"
prefill = list("androgynorovir" = 1)
/obj/item/weapon/reagent_containers/glass/beaker/vial/macrocillin
name = "vial (macrocillin)"
prefill = list("macrocillin" = 1)
/obj/item/weapon/reagent_containers/glass/beaker/vial/microcillin
name = "vial (microcillin)"
prefill = list("microcillin" = 1)
/obj/item/weapon/reagent_containers/glass/beaker/vial/normalcillin
name = "vial (normalcillin)"
prefill = list("normalcillin" = 1)
/obj/item/weapon/reagent_containers/glass/beaker/vial/supermatter
name = "vial (supermatter)"
desc = "A glass vial containing the extremely dangerous results of grinding a shard of supermatter down to a fine powder."
@@ -151,6 +151,8 @@
desc = "A rapid and safe way to administer small amounts of drugs by untrained or trained personnel."
icon_state = "blue"
item_state = "blue"
w_class = ITEMSIZE_TINY
slot_flags = SLOT_EARS
amount_per_transfer_from_this = 5
volume = 5
filled = 1
+26
View File
@@ -14,6 +14,32 @@
if(prob(3))
M.emote(pick("blush", "moan", "moan", "giggle"))
/datum/reagent/sorbitol
name = "Sorbitol"
id = "sorbitol"
description = "A frothy green liquid, for causing cellular-level hetrogenous structure merging."
reagent_state = LIQUID
color = "#10881A"
overdose = REAGENTS_OVERDOSE
/datum/reagent/sorbitol/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
M.make_dizzy(1)
for(var/obj/belly/B as anything in M.vore_organs)
if(B.digest_mode == DM_UNABSORB) //Don't affect bellies set to unabsorb
continue
for(var/mob/living/P in B)
if(P.absorbed || !P.absorbable)
continue
else if(prob(10))
B.absorb_living(P)
if(B.reagent_mode_flags & DM_FLAG_REAGENTSABSORB && B.reagents.total_volume < B.reagents.maximum_volume) //CHOMPedit: absorption reagent production
B.GenerateBellyReagents_absorbed()
///GENDER CHANGE REAGENTS////
+7
View File
@@ -6,6 +6,13 @@
/obj/machinery/disposal/wall/cleaner/flush()
flick("[icon_state]-flush", src)
for(var/obj/item/weapon/storage/i in src)
if(istype(i, /obj/item/weapon/storage))
var/list/storage_items = i.return_inv()
for(var/obj/item/item in storage_items)
item.decontaminate()
for(var/obj/item/i in src)
if(istype(i, /obj/item))
i.decontaminate()
@@ -33,7 +33,7 @@ If the spell_projectile is seeking, it will update its target every process and
if(istype(projectile, /obj/item/projectile/spell_projectile))
var/obj/item/projectile/spell_projectile/SP = projectile
SP.carried = src //casting is magical
projectile.def_zone = check_zone("chest")
projectile.def_zone = check_zone(BP_TORSO)
projectile.old_style_target(target)
projectile.fire()
+125
View File
@@ -0,0 +1,125 @@
/proc/consonant()
return pick("B","C","D","F","G","H","J","K","L","M","N","P","Q","R","S","T","V","W","X","Y","Z")
/proc/vowel()
return pick("A", "E", "I", "O", "U")
/proc/ucfirst(var/S)
return "[uppertext(ascii2text(text2ascii(S, 1)))][copytext(S, 2)]"
/proc/ucfirsts(var/S)
var/list/L = splittext(S, " ")
var/list/M = list()
for (var/P in L)
M += ucfirst(P)
return jointext(M, " ")
GLOBAL_LIST_EMPTY(FrozenAccounts)
/proc/list_frozen()
for (var/A in GLOB.FrozenAccounts)
to_chat(usr, "[A]: [length(GLOB.FrozenAccounts[A])] borrows")
/datum/article
var/headline = "Something big is happening"
var/subtitle = "Investors panic as stock market collapses"
var/article = "God, it's going to be fun to randomly generate this."
var/author = "P. Pubbie"
var/spacetime = ""
var/opinion = 0
var/ticks = 0
var/datum/stock/about = null
var/outlet = ""
var/static/list/outlets = list()
var/static/list/default_tokens = list( \
"buy" = list("buy!", "buy, buy, buy!", "get in now!", "ride the share value to the stars!"), \
"company" = list("company", "corporation", "conglomerate", "enterprise", "venture"), \
"complete" = list("complete", "total", "absolute", "incredible"), \
"country" = list("Space", "Argentina", "Hungary", "United States of America", "United Space", "Space Federation", "Nanotrasen", "The Wizard Federation", "United Kingdom", "Poland", "The Syndicate", "Australia", "Serbia", "The European Union", "The Illuminati", "The New World Order", "Eurasian Union", "Asian Union", "United Arab Emirates", "Arabian League", "United States of Africa", "Mars Federation", "Allied Colonies of Jupiter", "Saturn's Ring", "Fringe Republic of Formerly Planet Pluto"), \
"development" = list("development", "unfolding of events", "turn of events", "new shit"), \
"dip" = list("dip", "fall", "plunge", "decrease"), \
"excited" = list("excited", "euphoric", "exhilarated", "thrilled", "stimulated"), \
"expand_influence" = list("expands their influence over", "continues to dominate", "gains traction in", "rolls their new product line out in"), \
"failure" = list("failure", "meltdown", "breakdown", "crash", "defeat", "wreck"), \
"famous" = list("famous", "prominent", "leading", "renowned", "expert"), \
"hit_shelves" = list("hit the shelves", "appeared on the market", "came out", "was released"), \
"industry" = list("industry", "sector"), \
"industrial" = list("industrial"), \
"jobs" = list("workers"), \
"negative_outcome" = list("it's not leaving the shelves", "nobody seems to care", "it's a huge money sink", "they have already pulled all advertising and marketing support"), \
"neutral_outcome" = list("it's not lifting off as expected", "it's not selling according to expectations", "it's only generating enough profit to cover the marketing and manufacturing costs", "it does not look like it will become a massive success", "it's experiencing modest sales"), \
"positive_outcome" = list("it's already sold out", "it has already sold over one billion units", "suppliers cannot keep up with the wild demand", "several companies using this new technology are already reporting a projected increase in profits"), \
"resounding" = list("resounding", "tremendous", "total", "massive", "terrific", "colossal"), \
"rise" = list("rise", "increase", "fly off the positive side of the charts", "skyrocket", "lift off"), \
"sell" = list("sell!", "sell, sell, sell!", "bail!", "abandon ship!", "get out before it's too late!", "evacuate!", "withdraw!"), \
"signifying" = list("signifying", "indicating", "implying", "displaying", "suggesting"), \
"sneak_peek" = list("review", "sneak peek", "preview", "exclusive look"), \
"stock_market" = list("stock market", "stock exchange"), \
"stockholder" = list("stockholder", "shareholder"), \
"success" = list("success", "triumph", "victory"), \
"this_time" = list("this week", "last week", "this month", "yesterday", "today", "a few days ago") \
)
/datum/article/New()
..()
if ((outlets.len && !prob(100 / (outlets.len + 1))) || !outlets.len)
var/ON = generateOutletName()
if (!(ON in outlets))
outlets[ON] = list()
outlet = ON
else
outlet = pick(outlets)
var/list/authors = outlets[outlet]
if ((authors.len && !prob(100 / (authors.len + 1))) || !authors.len)
var/AN = generateAuthorName()
outlets[outlet] += AN
author = AN
else
author = pick(authors)
ticks = world.time
/datum/article/proc/generateOutletName()
var/list/locations = list("Earth", "Luna", "Mars", "Saturn", "Jupiter", "Uranus", "Pluto", "Europa", "Io", "Phobos", "Deimos", "Space", "Venus", "Neptune", "Mercury", "Kalliope", "Ganymede", "Callisto", "Amalthea", "Himalia", "Orion", "Sybil", "Basil", "Badger", "Terry", "Artyom")
var/list/nouns = list("Post", "Herald", "Sun", "Tribune", "Mail", "Times", "Journal", "Report")
var/list/timely = list("Daily", "Hourly", "Weekly", "Biweekly", "Monthly", "Yearly")
switch(rand(1,2))
if (1)
return "The [pick(locations)] [pick(nouns)]"
if (2)
return "The [pick(timely)] [pick(nouns)]"
/datum/article/proc/generateAuthorName()
switch(rand(1,3))
if (1)
return "[consonant()]. [pick(last_names)]"
if (2)
return "[prob(50) ? pick(first_names_male) : pick(first_names_female)] [consonant()].[prob(50) ? "[consonant()]. " : null] [pick(last_names)]"
if (3)
return "[prob(50) ? pick(first_names_male) : pick(first_names_female)] \"[prob(50) ? pick(first_names_male) : pick(first_names_female)]\" [pick(last_names)]"
/datum/article/proc/formatSpacetime()
var/ticksc = round(ticks/100)
ticksc = ticksc % 100000
var/ticksp = "[ticksc]"
while (length(ticksp) < 5)
ticksp = "0[ticksp]"
spacetime = "[ticksp][time2text(world.realtime, "MM")][time2text(world.realtime, "DD")][text2num(time2text(world.realtime, "YYYY"))+540]"
/datum/article/proc/formatArticle()
if (spacetime == "")
formatSpacetime()
var/output = "<div class='article'><div class='headline'>[headline]</div><div class='subtitle'>[subtitle]</div><div class='article-body'>[article]</div><div class='author'>[author]</div><div class='timestamp'>[spacetime]</div></div>"
return output
/datum/article/proc/detokenize(var/token_string, var/list/industry_tokens, var/list/product_tokens = list())
var/list/T_list = default_tokens.Copy()
for (var/I in industry_tokens)
T_list[I] = industry_tokens[I]
for (var/I in product_tokens)
T_list[I] = list(product_tokens[I])
for (var/I in T_list)
token_string = replacetext(token_string, "%[I]%", pick(T_list[I]))
return ucfirst(token_string)
+336
View File
@@ -0,0 +1,336 @@
/obj/machinery/computer/stockexchange
name = "stock exchange computer"
desc = "A console that connects to the galactic stock market. Stocks trading involves substantial risk of loss and is not suitable for every cargo technician."
icon = 'icons/obj/computer.dmi'
icon_state = "stockmarket"
icon_screen = "stocks"
icon_keyboard = "stockmarket_key"
var/logged_in = "Cargo Department"
var/vmode = 1
light_color = LIGHT_COLOR_GREEN
/obj/machinery/computer/stockexchange/Initialize()
. = ..()
logged_in = "Cargo Department"
/obj/machinery/computer/stockexchange/attack_hand(mob/user)
if(..(user))
return
//if(!ai_control && issilicon(user))
// to_chat(user, "<span class='warning'>Access Denied.</span>")
// return TRUE
tgui_interact(user)
/obj/machinery/computer/stockexchange/proc/balance()
if (!logged_in)
return 0
return SSsupply.points
///// MAIN TGUI SCREEN /////
/obj/machinery/computer/stockexchange/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
add_fingerprint(usr)
switch(action)
if ("logout")
logged_in = null
if("stocks_buy")
var/datum/stock/S = locate(params["share"]) in GLOB.stockExchange.stocks
if (S)
buy_some_shares(S, usr)
if("stocks_sell")
var/datum/stock/S = locate(params["share"]) in GLOB.stockExchange.stocks
if (S)
sell_some_shares(S, usr)
if("stocks_check")
var/dat = "<html><head><title>Stock Transaction Logs</title></head><body><h2>Stock Transaction Logs</h2><div><a href='?src=[REF(src)];show_logs=1'>Refresh</a></div></br>"
for(var/D in GLOB.stockExchange.logs)
var/datum/stock_log/L = D
if(istype(L, /datum/stock_log/buy))
dat += "[L.time] | <b>[L.user_name]</b> bought <b>[L.stocks]</b> stocks at [L.shareprice] a share for <b>[L.money]</b> total credits in <b>[L.company_name]</b>.</br>"
continue
if(istype(L, /datum/stock_log/sell))
dat += "[L.time] | <b>[L.user_name]</b> sold <b>[L.stocks]</b> stocks at [L.shareprice] a share for <b>[L.money]</b> total credits from <b>[L.company_name]</b>.</br>"
continue
if(istype(L, /datum/stock_log/borrow))
dat += "[L.time] | <b>[L.user_name]</b> borrowed <b>[L.stocks]</b> stocks with a deposit of <b>[L.money]</b> credits in <b>[L.company_name]</b>.</br>"
continue
var/datum/browser/popup = new(usr, "stock_logs", "Stock Transaction Logs", 600, 400)
popup.set_content(dat)
popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
if("stocks_archive")
var/datum/stock/S = locate(params["share"])
if (logged_in && logged_in != "")
var/list/LR = GLOB.stockExchange.last_read[S]
LR[logged_in] = world.time
var/dat = "<html><head><title>News feed for [S.name]</title></head><body><h2>News feed for [S.name]</h2><div><a href='?src=[REF(src)];archive=[REF(S)]'>Refresh</a></div>"
dat += "<div><h3>Events</h3>"
var/p = 0
for (var/datum/stockEvent/E in S.events)
if (E.hidden)
continue
if (p > 0)
dat += "<hr>"
dat += "<div><b>[E.current_title]</b></br>[E.current_desc]</div>"
p++
dat += "</div><hr><div><h3>Articles</h3>"
p = 0
for (var/datum/article/A in S.articles)
if (p > 0)
dat += "<hr>"
dat += "<div><b>[A.headline]</b><br><i>[A.subtitle]</i><br><br>[A.article]<br>- [A.author], [A.spacetime] (via <i>[A.outlet]</i>)</div>"
p++
dat += "</div></body></html>"
var/datum/browser/popup = new(usr, "archive_[S.name]", "Stock News", 600, 400)
popup.set_content(dat)
popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
if("stocks_history")
var/datum/stock/S = locate(params["share"]) in GLOB.stockExchange.stocks
if (S)
S.displayValues(usr)
if("stocks_cycle_view")
vmode++
if (vmode > 1)
vmode = 0
/obj/machinery/computer/stockexchange/tgui_data(mob/user)
var/list/data = list()
data["stationName"] = using_map.station_name
data["balance"] = balance()
if (vmode)
data["viewMode"] = "Full"
else
data["viewMode"] = "Compressed"
for (var/datum/stock/S in GLOB.stockExchange.last_read)
var/list/LR = GLOB.stockExchange.last_read[S]
if (!(logged_in in LR))
LR[logged_in] = 0
data["stocks"] = list()
if (vmode)
for (var/datum/stock/S in GLOB.stockExchange.stocks)
var/mystocks = 0
if (logged_in && (logged_in in S.shareholders))
mystocks = S.shareholders[logged_in]
var/value = 0
if (!S.bankrupt)
value = S.current_value
data["stocks"] += list(list(
"REF" = REF(S),
"valueChange" = S.disp_value_change, // > 0 is +, < 0 is -, else its =
"bankrupt" = S.bankrupt,
"ID" = S.short_name,
"Name" = S.name,
"Value" = value,
"Owned" = mystocks,
"Avail" = S.available_shares,
"Products" = S.products,
))
var/news = 0
if (logged_in)
var/list/LR = GLOB.stockExchange.last_read[S]
var/lrt = LR[logged_in]
for (var/datum/article/A in S.articles)
if (A.ticks > lrt)
news = 1
break
if (!news)
for (var/datum/stockEvent/E in S.events)
if (E.last_change > lrt && !E.hidden)
news = 1
else
for (var/datum/stock/S in GLOB.stockExchange.stocks)
var/mystocks = 0
if (logged_in && (logged_in in S.shareholders))
mystocks = S.shareholders[logged_in]
var/unification = 0
if (S.last_unification)
unification = DisplayTimeText(world.time - S.last_unification)
data["stocks"] += list(list(
"REF" = REF(S),
"bankrupt" = S.bankrupt,
"ID" = S.short_name,
"Name" = S.name,
"Owned" = mystocks,
"Avail" = S.available_shares,
"Unification" = unification,
"Products" = S.products,
))
var/news = 0
if (logged_in)
var/list/LR = GLOB.stockExchange.last_read[S]
var/lrt = LR[logged_in]
for (var/datum/article/A in S.articles)
if (A.ticks > lrt)
news = 1
break
if (!news)
for (var/datum/stockEvent/E in S.events)
if (E.last_change > lrt && !E.hidden)
news = 1
break
return data
/obj/machinery/computer/stockexchange/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "StockExchange")
ui.open()
///// HISTORY SCREEN /////
/obj/machinery/computer/stockexchange/history/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "StockExchangeHistory")
ui.open()
/obj/machinery/computer/stockexchange/history/tgui_data(mob/user)
var/list/data = list()
//data["var"] = var
return data
/obj/machinery/computer/stockexchange/history/tgui_act(action, params)
if(..())
return
switch(action)
if("copypasta")
//var/newvar = params["var"]
// A demo of proper input sanitation.
//var = CLAMP(newvar, min_val, max_val)
. = TRUE
///// ARCHIVE SCREEN /////
/obj/machinery/computer/stockexchange/archive/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "StockExchangeArchive")
ui.open()
/obj/machinery/computer/stockexchange/archive/tgui_data(mob/user)
var/list/data = list()
//data["var"] = var
return data
/obj/machinery/computer/stockexchange/archive/tgui_act(action, params)
if(..())
return
switch(action)
if("copypasta")
//var/newvar = params["var"]
// A demo of proper input sanitation.
//var = CLAMP(newvar, min_val, max_val)
. = TRUE
///// PROCS /////
/obj/machinery/computer/stockexchange/proc/sell_some_shares(var/datum/stock/S, var/mob/user)
if (!user || !S)
return
var/li = logged_in
if (!li)
to_chat(user, "<span class='danger'>No active account on the console!</span>")
return
var/b = SSsupply.points
var/avail = S.shareholders[logged_in]
if (!avail)
to_chat(user, "<span class='danger'>This account does not own any shares of [S.name]!</span>")
return
var/price = S.current_value
var/amt = round(input(user, "How many shares? \n(Have: [avail], unit price: [price])", "Sell shares in [S.name]", 0) as num|null)
amt = min(amt, S.shareholders[logged_in])
if (!user || (!(user in range(1, src)) && iscarbon(user)))
return
if (!amt)
return
if (li != logged_in)
return
b = SSsupply.points
if (!isnum(b))
to_chat(user, "<span class='danger'>No active account on the console!</span>")
return
var/total = amt * S.current_value
if (!S.sellShares(logged_in, amt))
to_chat(user, "<span class='danger'>Could not complete transaction.</span>")
return
to_chat(user, "<span class='notice'>Sold [amt] shares of [S.name] at [S.current_value] a share for [total] credits.</span>")
GLOB.stockExchange.add_log(/datum/stock_log/sell, user.name, S.name, amt, S.current_value, total)
/obj/machinery/computer/stockexchange/proc/buy_some_shares(var/datum/stock/S, var/mob/user)
if (!user || !S)
return
var/li = logged_in
if (!li)
to_chat(user, "<span class='danger'>No active account on the console!</span>")
return
var/b = balance()
if (!isnum(b))
to_chat(user, "<span class='danger'>No active account on the console!</span>")
return
var/avail = S.available_shares
var/price = S.current_value
var/canbuy = round(b / price)
var/amt = round(input(user, "How many shares? \n(Available: [avail], unit price: [price], can buy: [canbuy])", "Buy shares in [S.name]", 0) as num|null)
if (!user || (!(user in range(1, src)) && iscarbon(user)))
return
if (li != logged_in)
return
b = balance()
if (!isnum(b))
to_chat(user, "<span class='danger'>No active account on the console!</span>")
return
amt = min(amt, S.available_shares, round(b / S.current_value))
if (!amt)
return
if (!S.buyShares(logged_in, amt))
to_chat(user, "<span class='danger'>Could not complete transaction.</span>")
return
var/total = amt * S.current_value
to_chat(user, "<span class='notice'>Bought [amt] shares of [S.name] at [S.current_value] a share for [total] credits.</span>")
GLOB.stockExchange.add_log(/datum/stock_log/buy, user.name, S.name, amt, S.current_value, total)
/obj/machinery/computer/stockexchange/proc/do_borrowing_deal(var/datum/borrow/B, var/mob/user)
if (B.stock.borrow(B, logged_in))
to_chat(user, "<span class='notice'>You successfully borrowed [B.share_amount] shares. Deposit: [B.deposit].</span>")
GLOB.stockExchange.add_log(/datum/stock_log/borrow, user.name, B.stock.name, B.share_amount, B.deposit)
else
to_chat(user, "<span class='danger'>Could not complete transaction. Check your account balance.</span>")
/obj/machinery/computer/stockexchange/Topic(href, href_list)
if (..())
return 1
if (!usr || (!(usr in range(1, src)) && iscarbon(usr)))
usr.machine = src
src.add_fingerprint(usr)
src.updateUsrDialog()
+233
View File
@@ -0,0 +1,233 @@
#define TIME_MULTIPLIER 0.7 // so I can speed up/slow down shit
/datum/stockEvent
var/name = "event"
var/next_phase = 0
var/datum/stock/company = null
var/current_title = "A company holding a pangalactic conference in the Seattle Conference Center, Seattle, Earth"
var/current_desc = "We will continue to monitor their stocks as the situation unfolds."
var/phase_id = 0
var/hidden = 0
var/finished = 0
var/last_change = 0
/datum/stockEvent/process()
if (finished)
return
if (world.time > next_phase)
transition()
/datum/stockEvent/proc/transition()
return
/datum/stockEvent/proc/spacetime(var/ticks)
var/seconds = round(ticks / 10)
var/minutes = round(seconds / 60)
seconds -= minutes * 60
return "[minutes] minute(s) and [seconds] second(s)"
/datum/stockEvent/product
name = "product"
var/product_name = ""
var/datum/article/product_article = null
var/effect = 0
/datum/stockEvent/product/New(var/datum/stock/S)
company = S
var/mins = rand(5*TIME_MULTIPLIER,20*TIME_MULTIPLIER)
next_phase = mins * (600*TIME_MULTIPLIER) + world.time
current_title = "Product demo"
current_desc = S.industry.detokenize("[S.name] will unveil a new product on an upcoming %industrial% conference held at spacetime [spacetime(next_phase)]")
S.addEvent(src)
/datum/stockEvent/product/transition()
last_change = world.time
switch (phase_id)
if (0)
next_phase = world.time + rand(300*TIME_MULTIPLIER, 600*TIME_MULTIPLIER) * (10*TIME_MULTIPLIER)
product_name = company.industry.generateProductName(company.name)
current_title = "Product release: [product_name]"
current_desc = "[company.name] unveiled their newest product at a conference, [product_name]Product release is expected to happen at spacetime [spacetime(next_phase)]."
var/datum/article/A = company.industry.generateInCharacterProductArticle(product_name, company)
product_article = A
effect = A.opinion + rand(-1, 1)
company.affectPublicOpinion(effect)
phase_id = 1
if (1)
finished = 1
hidden = 1
company.addArticle(product_article)
effect += product_article.opinion * 5
company.affectPublicOpinion(effect)
phase_id = 2
company.generateEvent(type)
/datum/stockEvent/bankruptcy
name = "bankruptcy"
var/effect = 0
var/bailout_millions = 0
/datum/stockEvent/bankruptcy/New(var/datum/stock/S)
hidden = 1
company = S
var/mins = rand(9*TIME_MULTIPLIER,60*TIME_MULTIPLIER)
bailout_millions = rand(70, 190)
next_phase = mins * 300*TIME_MULTIPLIER + world.time
current_title = ""
current_desc = ""
S.addEvent(src)
/datum/stockEvent/bankruptcy/transition()
switch (phase_id)
if (0)
next_phase = world.time + rand(300*TIME_MULTIPLIER, 600*TIME_MULTIPLIER) * (10*TIME_MULTIPLIER)
var/datum/article/A = generateBankruptcyArticle()
if (!A.opinion)
effect = rand(5) * (prob(50) ? -1 : 1)
else
effect = prob(25) ? -A.opinion * rand(8) : A.opinion * rand(4)
company.addArticle(A)
company.affectPublicOpinion(rand(-6, -3))
hidden = 0
current_title = "Bailout pending due to bankruptcy"
current_desc = "The government prepared a press release, which will occur at spacetime [spacetime(next_phase)]."
phase_id = 1
if (1)
next_phase = world.time + rand(300*TIME_MULTIPLIER, 600*TIME_MULTIPLIER) * (10*TIME_MULTIPLIER)
finished = 1
if (effect <= -5 && prob(10))
current_title = "[company.name]: Complete crash"
current_desc = "The company had gone bankrupt, was not bailed out and could not recover. No further stock trade will take place. All shares in the company are effectively worthless."
company.bankrupt = 1
for (var/X in company.shareholders)
var/amt = company.shareholders[X]
GLOB.stockExchange.balanceLog(X, -amt * company.current_value)
company.shareholders = list()
company.current_value = 0
company.borrow_brokers = list()
GLOB.stockExchange.generateStocks(1)
var/bailout = (effect > 0 && prob(80)) || (effect < 0 && prob(20))
current_title = "[company.name] [bailout ? "bailed out" : "on a painful rebound"]"
if (bailout)
current_desc = "The company has been bailed out by the government. Investors are highly optimistic."
company.affectPublicOpinion(abs(effect) * 2)
else
current_desc = "The company was not bailed out, but managed to crawl out of bankruptcy. Stockholder trust is severely dented."
company.affectPublicOpinion(-abs(effect) / 2)
company.generateEvent(type)
/datum/stockEvent/bankruptcy/proc/generateBankruptcyArticle()
var/datum/article/A = new
var/list/bankrupt_reason = list("investor pessimism", "failure of product lines", "economic recession", "overblown inflation", "overblown deflation", "collapsed pyramid schemes", "a Ponzi scheme", "economic terrorism", "extreme hedonism", "unfavourable economic climate", "rampant government corruption", "divine conspiracy", "some total bullshit", "volatile plans")
A.about = company
A.headline = pick( "[company.name] filing for bankruptcy", \
"[company.name] unable to pay, investors run", \
"[company.name] crashes, in foreclosure", \
"[company.name] in dire need of credits")
A.subtitle = "Investors panic, bailout pending"
if (prob(15))
A.opinion = rand(-1, 1)
var/article = "Another one might bite the dust: [company.current_trend > 0 ? "despite their positive trend" : "in line with their failing model"], [company.name] files for bankruptcy citing [pick(bankrupt_reason)]. The president of %country% has been asked to bail the company out, "
if (!A.opinion)
article += "but no answer has been given by the government to date. Our tip to stay safe is: %sell%"
else if (A.opinion > 0)
article += "and the government responded positively. When the share value hits its lowest, it is a safe bet to %buy%"
else
article += "but the outlook is not good. For investors, now would be an ideal time to %sell%"
A.article = A.detokenize(article, company.industry.tokens)
return A
/datum/stockEvent/arrest
name = "arrest"
var/female = 0
var/tname = "Elvis Presley"
var/position = "CEO"
var/offenses = "murder"
var/effect = 0
/datum/stockEvent/arrest/New(var/datum/stock/S)
hidden = 1
company = S
var/mins = rand(10*TIME_MULTIPLIER, 35*TIME_MULTIPLIER)
next_phase = mins * 600*TIME_MULTIPLIER + world.time
current_title = ""
current_desc = ""
female = prob(50)
if (prob(50))
position = "C[prob(20) ? vowel() : consonant()]O"
else
position = ucfirsts(company.industry.detokenize("Lead %industrial% Engineer"))
offenses = ""
var/list/O = list("corruption", "murder", "grand theft", "assault", "battery", "drug possession", "burglary", "theft", "grand sabotage", "bribery",
"disorderly conduct", "treason", "sedition", "shoplifting", "tax evasion", "tax fraud", "insurance fraud", "perjury", "kidnapping", "manslaughter", "vandalism", "forgery", "extortion", "embezzlement",
"public indecency", "public intoxication", "trespassing", "loitering", "littering", "vigilantism", "squatting", "panhandling", "arson", "spacepodjacking", "shuttlejacking", "carjacking", "singularityjacking",
"dereliction of duty", "spacecraft piracy", "music piracy", "tabletop game piracy", "software piracy", "escaping from space prison", "seniornapping", "clownnapping", "corginapping", "catnapping",
"sleeping on the job", "terrorism", "counterterrorism", "drug distribution", "insubordination", "jaywalking", "owning a computer", "owning a cellphone", "owning a PDA", "owning a pAI", "adultery",
"committing an unnatural act with another person", "corrupting public morals", "skateboarding without a license", "shitcurity", "bestiality", "erotic roleplay", "accidentally strangling a prostitute")
while (prob(60) && O.len > 2)
var/offense = pick(O)
O -= offense
offense = "[prob(20) ? "attempted " : (prob(20) ? "being accessory to " : null)][offense][prob(5) ? " of the [pick("first", "second", "third", "fourth", "fifth", "sixth")] degree" : null]"
if (offenses == "")
offenses = offense
else
offenses += ", [offense]"
offenses += " and [prob(20) ? "attempted " : null][pick(O)]" // lazy
S.addEvent(src)
/datum/stockEvent/arrest/transition()
switch (phase_id)
if (0)
var/name_part1
var/name_part2
name_part1 = pick("John ", "Jack ", "Jill ", "Peter ", "James ", "Lois ", "Zoey ")
name_part2 = pick("Bull", "Palmer", "Glass", "Ruin", "McCory", "Batty", "Lane")
tname = (name_part1 + name_part2)
next_phase = world.time + rand(300*TIME_MULTIPLIER, 600*TIME_MULTIPLIER) * (10*TIME_MULTIPLIER)
var/datum/article/A = generateArrestArticle()
if (!A.opinion)
effect = rand(5) * (prob(50) ? -1 : 1)
else
effect = prob(25) ? -A.opinion * rand(5) : A.opinion * rand(3)
company.addArticle(A)
company.affectPublicOpinion(rand(-3, -1))
hidden = 0
current_title = "Trial of [tname] ([position]) scheduled"
current_desc = "[female ? "She": "He"] has been charged with [offenses]; the trial is scheduled to occur at spacetime [spacetime(next_phase)]."
phase_id = 1
if (1)
next_phase = world.time + rand(300*TIME_MULTIPLIER, 600*TIME_MULTIPLIER) * (10*TIME_MULTIPLIER)
finished = 1
current_title = "[tname] [effect > 0 ? "acquitted" : "found guilty"]"
if (effect > 0)
current_desc = "The accused has been acquitted of all charges. Investors optimistic."
else
current_desc = "The accused has been found guilty of all charges. Investor trust takes massive hit."
company.affectPublicOpinion(effect)
company.generateEvent(type)
/datum/stockEvent/arrest/proc/generateArrestArticle()
var/datum/article/A = new
A.about = company
A.headline = company.industry.detokenize(pick( \
"[tname], [position] of [company.name] arrested", \
"[position] of [company.name] facing jail time", \
"[tname] behind bars", \
"[position] of %industrial% company before trial", \
"Police arrest [tname] in daring raid", \
"Job vacancy ahead: [company.name]'s [position] in serious trouble"))
A.subtitle = "[A.author] reporting directly from the courtroom"
if (prob(15))
A.opinion = rand(-1, 1)
var/article = "[pick("Security", "Law enforcement")] forces issued a statement that [tname], the [position] of [company.name], the %famous% %industrial% %company% was arrested %this_time%. The trial has been scheduled and the statement reports that the arrested individual is being charged with [offenses]. "
if (!A.opinion)
article += "While we cannot predict the outcome of this trial, our tip to stay safe is: %sell%"
else if (A.opinion > 0)
article += "Our own investigation shows that these charges are baseless and the arrest is most likely a publicity stunt. Our advice? You should %buy%"
else
article += "[tname] has a prior history of similar misdeeds and we're confident the charges will stand. For investors, now would be an ideal time to %sell%"
A.article = A.detokenize(article, company.industry.tokens)
return A
+233
View File
@@ -0,0 +1,233 @@
/datum/industry
var/name = "Industry"
var/list/tokens = list()
var/list/title_templates = list("The brand new %product_name% by %company_name% will revolutionize %industry%", \
"%jobs% rejoice as %product_name% hits shelves", \
"Does %product_name% threaten to reorganize the %industrial% status quo?", \
"%company_name% headed toward corporate renaissance with %product_name%")
var/list/title_templates_neutral = list("%product_name%: as if nothing happened", \
"Nothing new but the name: %product_name% not quite exciting %jobs%", \
"Same old %company_name%, same old product", \
"%product_name% underwhelms, but sells")
var/list/title_templates_bad = list("%product_name% shaping up to be the disappointment of the century", \
"Recipe for disaster: %company_name% releases %product_name%", \
"Atrocious quality - %jobs% boycott %product_name%", \
"%product_name%: Inside the worst product launch in recent history")
var/list/title_templates_ooc = list("%company_name% is looking to enter the %industry% playing field with %product_name%", \
"%company_name% broadens spectrum, %product_name% is their latest and greatest")
var/list/subtitle_templates = list( "%author% investigates whether or not you should invest!", \
"%outlet%'s very own %author% takes it to the magnifying glass", \
"%outlet% lets you know if you should use it", \
"Read our top tips for investors", \
"%author% wants you to know if it's a safe bet to buy")
/datum/industry/proc/generateProductName(var/company_name)
return
/datum/industry/proc/generateInCharacterProductArticle(var/product_name, var/datum/stock/S)
var/datum/article/A = new
var/list/add_tokens = list("company_name" = S.name, "product_name" = product_name, "outlet" = A.outlet, "author" = A.author)
A.about = S
A.opinion = rand(-1, 1)
A.subtitle = A.detokenize(pick(subtitle_templates), tokens, add_tokens)
var/article = {"%company_name% %expand_influence% %industry%. [ucfirst(product_name)] %hit_shelves% %this_time% "}
if (A.opinion > 0)
A.headline = A.detokenize(pick(title_templates), tokens, add_tokens)
article += "but %positive_outcome%, %signifying% the %resounding% %success% the product is. The %stock_market% is %excited% over this %development%, and %stockholder% optimism is expected to %rise% as well as the stock value. Our advice: %buy%."
else if (A.opinion == 0)
A.headline = A.detokenize(pick(title_templates_neutral), tokens, add_tokens)
article += "but %neutral_outcome%. For the average %stockholder%, no significant change on the market will be apparent over this %development%. Our advice is to continue investing as if this product was never released."
else
A.headline = A.detokenize(pick(title_templates_bad), tokens, add_tokens)
article += "but %negative_outcome%. Following this %complete% %failure%, %stockholder% optimism and stock value are projected to %dip%. Our advice: %sell%."
A.article = A.detokenize(article, tokens, add_tokens)
return A
/datum/industry/proc/detokenize(var/str)
for (var/T in tokens)
str = replacetext(str, "%[T]%", pick(tokens[T]))
return str
/datum/industry/agriculture
name = "Agriculture"
tokens = list( \
"industry" = list("agriculture", "farming", "botany", "horticulture", "hydroponics"), \
"industrial" = list("agricultural", "horticultural", "botanical"), \
"jobs" = list("farmers", "agricultural experts", "botanists", "assistant gardeners")
)
title_templates = list( "The brand new %product_name% by %company_name% will revolutionize %industry%", \
"%jobs% rejoice as %product_name% hits shelves", \
"Does %product name% threaten to reorganize the %industrial% status quo?", \
"Took it for a field trip: our first %sneak_peek% of %product_name%.", \
"Reaping the fruits of %product_name% - %sneak_peek% by %author%", \
"Cultivating a new %industrial% future with %product_name%", \
"%company_name% grows and thrives: %product_name% now on the farmer's market", \
"It's almost harvest season: %product_name% promises to ease your life", \
"Become the best on the farmer's market with %product_name%", \
"%product_name%: a gene-modified reimagination of an age-old classic")
title_templates_ooc = list( "%company_name% is looking to enter the %industry% playing field with %product_name%", \
"A questionable decision: %product_name% grown on the soil of %company_name%", \
"%company_name% broadens spectrum, %product_name% is their latest and greatest", \
"Will %company_name% grow on %industrial% wasteland? Owners of %product_name% may decide", \
"%company_name% looking to reap profits off the %industrial% sector with %product_name%")
/datum/industry/agriculture/generateProductName(var/company_name)
var/list/products = list("water tank", "cattle prod", "scythe", "plough", "sickle", "cultivator", "loy", "spade", "hoe", "daisy grubber", "cotton gin")
var/list/prefix = list("[company_name]'s ", "The [company_name] ", "The fully automatic ", "The full-duplex ", "The semi-automatic ", "The drone-mounted ", "The industry-leading ", "The world-class ")
var/list/suffix = list(" of farming", " multiplex", " +[rand(1,15)]", " [consonant()][rand(1000, 9999)]", " hybrid", " maximus", " extreme")
return "[pick(prefix)][pick(products)][pick(suffix)]. "
/datum/industry/it
name = "Information Technology"
tokens = list( \
"industry" = list("information technology", "computing", "computer industry"), \
"industrial" = list("information technological", "computing", "computer industrial"), \
"jobs" = list("coders", "electricians", "engineers", "programmers", "devops experts", "developers")
)
/datum/industry/it/proc/latin_number(n)
if (n < 20 || !(n % 10))
switch(n)
if (0)
return "Nihil"
if (1)
return "Unus"
if (2)
return "Duo"
if (3)
return "Tres"
if (4)
return "Quattour"
if (5)
return "Quinque"
if (6)
return "Sex"
if (7)
return "Septem"
if (8)
return "Octo"
if (9)
return "Novem"
if (10)
return "Decim"
if (11)
return "Undecim"
if (12)
return "Duodecim"
if (13)
return "Tredecim"
if (14)
return "Quattourdecim"
if (15)
return "Quindecim"
if (16)
return "Sedecim"
if (17)
return "Septdecim"
if (18)
return "Duodeviginti"
if (19)
return "Undeviginti"
if (20)
return "Viginti"
if (30)
return "Triginta"
if (40)
return "Quadriginta"
if (50)
return "Quinquaginta"
if (60)
return "Sexaginta"
if (70)
return "Septuaginta"
if (80)
return "Octoginta"
if (90)
return "Nonaginta"
else
return "[latin_number(n - (n % 10))] [lowertext(latin_number(n % 10))]"
/datum/industry/it/generateProductName(var/company_name)
var/list/products = list("generator", "laptop", "keyboard", "memory card", "display", "operating system", "processor", "graphics card", "nanobots", "power supply", "pAI", "mech", "capacitor", "cell")
var/list/prefix = list("The [company_name] ", "The high performance ", "The mobile ", "The portable ", "The professional ", "The extreme ", "The incredible ", "The blazing fast ", "The bleeding edge ", "The bluespace-powered ", null)
var/L = pick(consonant(), "Seed ", "Radiant ", "Robust ", "Pentathon ", "Athlete ", "Phantom ", "Semper Fi ")
var/N = rand(1, 99)
var/prefix2 = "[L][N][prob(5) ? " " + latin_number(N) : null]"
return "[pick(prefix)][prefix2] [pick(products)]. "
/datum/industry/communications
name = "Communications"
tokens = list( \
"industry" = list("telecommunications", "telecomms"), \
"industrial" = list("telecommunicational"), \
"jobs" = list("electrical engineers", "microengineers", "developers")
)
/datum/industry/communications/generateProductName(var/company_name)
var/list/products = list("mobile phone", "PDA", "tablet computer", "newscaster", "social network")
var/list/prefix = list("The [company_name] ", "The high performance ", "The mobile ", "The portable ", "The professional ", "The extreme ", "The incredible ", "The blazing fast ", "The bleeding edge ", null)
var/L = pick("[lowertext(consonant())]Phone ", "Universe ", "Xperience ", "Next ", "Engin-Y ", "Cyborg ", "[consonant()]")
var/N = rand(1,99)
var/prefix2 = "[L][N][prob(25) ? pick(" Tiny", " Mini", " Micro", " Slim", " Water", " Air", " Fire", " Earth", " Nano", " Pico", " Femto", " Planck") : null]"
return "[pick(prefix)][prefix2] [pick(products)]. "
/datum/industry/health
name = "Medicine"
tokens = list( \
"industry" = list("medicine"), \
"industrial" = list("medicinal"), \
"jobs" = list("medical doctors", "nurses", "paramedics", "psychologists", "psychiatrists", "chemists")
)
/datum/industry/health/generateProductName(var/company_name)
var/list/prefix = list("amino", "nucleo", "nitro", "panto", "meth", "eth", "as", "algo", "coca", "hero", "lotsu", "opiod", "morph", "trinitro", "prop", "but", "acet", "acyclo", "lansop", "dyclo", "hydro", "oxycod", "vicod", "cannabi", "cryo", "dex", "chloro")
var/list/suffix = list("phen", "pirin", "pyrine", "ane", "amphetamine", "prazoline", "ine", "yl", "amine", "aminophen", "one", "ide", "phenate", "anol", "toulene", "glycerine", "vir", "tol", "trinic", "oxide")
var/list/uses = list("antidepressant", "analgesic", "anesthetic", "antiretroviral", "antiviral", "antibiotic", "cough drop", "depressant", "hangover cure", "homeopathic", "fertility drug", "hypnotic", "narcotic", "laxative", "multivitamin", "patch", "purgative", "relaxant", "steroid", "sleeping pill", "suppository", "tranquilizer")
return "[pick(prefix)][pick(suffix)], the [pick(uses)]. "
/datum/industry/consumer
name = "Consumer"
tokens = list( \
"industry" = list("shops", "stores"), \
"industrial" = list("consumer industrial"), \
"jobs" = list("shopkeepers", "assistants", "manual daytime hygiene engineers", "janitors", "chefs", "cooks")
)
/datum/industry/consumer/generateProductName(var/company)
var/list/meat = list("chicken", "lizard", "corgi", "monkey", "goat", "fly", "xenomorph", "human", "walrus", "wendigo", "bear", "clown", "turkey", "pork", "carp", "crab", "mimic", "mystery")
var/list/qualifier = list("synthetic", "organic", "bio", "diet", "sugar-free", "paleolithic", "homeopathic", "recycled", "reclaimed", "vat-grown")
return "The [pick(qualifier)] [pick(meat)] meat product line. "
/datum/industry/mining
name = "Mining"
tokens = list( \
"industry" = list("mines", "large scale mining operations"), \
"industrial" = list("resource acquisitional"), \
"jobs" = list("shaft miners", "drill operators", "mining foremen")
)
/datum/industry/mining/generateProductName(var/company)
var/list/equipment = list("drill", "pickaxe", "shovel", "jackhammer", "mini-pickaxe", "power hammer", "power gloves", "power armor", "hardsuit", "kinetic accelerator", "resonator", "oxygen tank", "emergency bike horn")
var/list/material = list("mauxite", "pharosium", "molitz", "adamantium", "mithril", "cobryl", "bohrum", "claretine", "viscerite", "syreline", "cerenkite", "plasmastone", "gold", "koshmarite", "phoron", "carbon dioxide", "powered")
return "The [pick(material)] [pick(equipment)]. "
/datum/industry/defense
name = "Defense"
tokens = list ( \
"industry" = list("defense", "warfare", "security", "law enforcement"), \
"industrial" = list("defense"), \
"jobs" = list("security officers", "government officials", "soldiers", "weapons engineers")
)
/datum/industry/defense/generateProductName(var/company)
var/list/equipment = list("energy gun", "laser gun", "machine gun", "grenade", "stun baton", "artillery", "bomb", "attack drone", "missile", "chem sprayer")
var/list/material = list("bluespace", "stealth", "heat-seeking", "crime-seeking", "wide-range", "bioterror", "auto-reloading", "smart", "sentient", "rapid-fire", "species-targeting", "mass-market", "perpetual-motion", "nuclear", "fission", "fusion")
return "The [pick(material)] [pick(equipment)]. "
+14
View File
@@ -0,0 +1,14 @@
/datum/stock_log
var/user_name = ""
var/company_name = ""
var/shareprice
var/money
var/stocks
var/time
/datum/stock_log/buy
/datum/stock_log/sell
/datum/stock_log/borrow
+168
View File
@@ -0,0 +1,168 @@
/datum/stockMarket
var/list/stocks = list()
var/list/balances = list()
var/list/last_read = list()
var/list/stockBrokers = list()
var/list/logs = list()
/datum/stockMarket/New()
..()
generateBrokers()
generateStocks()
START_PROCESSING(SSobj, src)
/datum/stockMarket/proc/balanceLog(var/whose, var/net)
if (!(whose in balances))
balances[whose] = net
else
balances[whose] += net
/datum/stockMarket/proc/generateBrokers()
stockBrokers = list()
var/list/fnames = list("Goldman", "Edward", "James", "Luis", "Alexander", "Walter", "Eugene", "Mary", "Morgan", "Jane", "Elizabeth", "Xavier", "Hayden", "Samuel", "Lee")
var/list/names = list("Johnson", "Rothschild", "Sachs", "Stanley", "Hepburn", "Brown", "McColl", "Fischer", "Edwards", "Becker", "Witter", "Walker", "Lambert", "Smith", "Montgomery", "Lynch", "Roosevelt", "Lehman")
var/list/locations = list("Earth", "Luna", "Mars", "Saturn", "Jupiter", "Uranus", "Pluto", "Europa", "Io", "Phobos", "Deimos", "Space", "Venus", "Neptune", "Mercury", "Kalliope", "Ganymede", "Callisto", "Amalthea", "Himalia", "Sybil", "Basil", "Badger", "Terry", "Artyom")
var/list/first = list("The", "First", "Premier", "Finest", "Prime")
var/list/company = list("Investments", "Securities", "Corporation", "Bank", "Brokerage", "& Co.", "Brothers", "& Sons", "Investement Firm", "Union", "Partners", "Capital", "Trade", "Holdings")
for(var/i in 1 to 5)
var/pname = ""
switch (rand(1,5))
if (1)
pname = "[prob(10) ? pick(first) + " " : null][pick(names)] [pick(company)]"
if (2)
pname = "[pick(names)] & [pick(names)][prob(25) ? " " + pick(company) : null]"
if (3)
pname = "[prob(45) ? pick(first) + " " : null][pick(locations)] [pick(company)]"
if (4)
pname = "[prob(10) ? "The " : null][pick(names)] [pick(locations)] [pick(company)]"
if (5)
pname = "[prob(10) ? "The " : null][pick(fnames)] [pick(names)][prob(10) ? " " + pick(company) : null]"
if (pname in stockBrokers)
i--
continue
stockBrokers += pname
/datum/stockMarket/proc/generateDesignation(var/name)
if (length(name) <= 4)
return uppertext(name)
var/list/w = splittext(name, " ")
if (w.len >= 2)
var/d = ""
for(var/i in 1 to min(5, w.len))
d += uppertext(ascii2text(text2ascii(w[i], 1)))
return d
else
var/d = uppertext(ascii2text(text2ascii(name, 1)))
for(var/i in 2 to length(name))
if (prob(100 / i))
d += uppertext(ascii2text(text2ascii(name, i)))
return d
/datum/stockMarket/proc/generateStocks(var/amt = 15)
var/list/fruits = list("Banana", "Mimana", "Watermelon", "Ambrosia", "Pomegranate", "Reishi", "Papaya", "Mango", "Tomato", "Conkerberry", "Wood", "Lychee", "Mandarin", "Harebell", "Pumpkin", "Rhubarb", "Tamarillo", "Yantok", "Ziziphus", "Oranges", "Gatfruit", "Daisy", "Kudzu")
var/list/tech_prefix = list("Nano", "Cyber", "Funk", "Astro", "Fusion", "Tera", "Exo", "Star", "Virtual", "Plasma", "Robust", "Bit", "Future", "Hugbox", "Carbon", "Nerf", "Buff", "Nova", "Space", "Meta", "Cyber")
var/list/tech_short = list("soft", "tech", "prog", "tec", "tek", "ware", "", "gadgets", "nics", "tric", "trasen", "tronic", "coin")
var/list/random_nouns = list("Johnson", "Cluwne", "General", "Specific", "Master", "King", "Queen", "Table", "Rupture", "Dynamic", "Massive", "Mega", "Giga", "Certain", "Singulo", "State", "National", "International", "Interplanetary", "Sector", "Planet", "Burn", "Robust", "Exotic", "Solar", "Lunar", "Chelp", "Corgi", "Lag", "Lizard")
var/list/company = list("Company", "Factory", "Incorporated", "Industries", "Group", "Consolidated", "GmbH", "LLC", "Ltd", "Inc.", "Association", "Limited", "Software", "Technology", "Programming", "IT Group", "Electronics", "Nanotechnology", "Farms", "Stores", "Mobile", "Motors", "Electric", "Designs", "Energy", "Pharmaceuticals", "Communications", "Wholesale", "Holding", "Health", "Machines", "Astrotech", "Gadgets", "Kinetics")
for (var/i = 1, i <= amt, i++)
var/datum/stock/S = new
var/sname = ""
switch (rand(1,6))
if(1)
while (sname == "" || sname == "FAG") // honestly it's a 0.6% chance per round this happens - or once in 166 rounds - so i'm accounting for it before someone yells at me
sname = "[consonant()][vowel()][consonant()]"
if (2)
sname = "[pick(tech_prefix)][pick(tech_short)][prob(20) ? " " + pick(company) : null]"
if (3 to 4)
var/fruit = pick(fruits)
fruits -= fruit
sname = "[prob(10) ? "The " : null][fruit][prob(40) ? " " + pick(company): null]"
if (5 to 6)
var/pname = pick(random_nouns)
random_nouns -= pname
switch (rand(1,3))
if (1)
sname = "[pname] & [pname]"
if (2)
sname = "[pname] [pick(company)]"
if (3)
sname = "[pname]"
S.name = sname
S.short_name = generateDesignation(S.name)
S.current_value = rand(10, 125)
var/dv = rand(10, 40) / 10
S.fluctuational_coefficient = prob(50) ? (1 / dv) : dv
S.average_optimism = rand(-10, 10) / 100
S.optimism = S.average_optimism + (rand(-40, 40) / 100)
S.current_trend = rand(-200, 200) / 10
S.last_trend = S.current_trend
S.disp_value_change = rand(-1, 1)
S.speculation = rand(-20, 20)
S.average_shares = round(rand(500, 10000) / 10)
S.outside_shareholders = rand(1000, 30000)
S.available_shares = rand(200000, 800000)
S.fluctuation_rate = rand(6, 20)
S.generateIndustry()
S.generateEvents()
stocks += S
last_read[S] = list()
/datum/stockMarket/process()
for (var/stock in stocks)
var/datum/stock/S = stock
S.process()
/datum/stockMarket/proc/add_log(var/log_type, var/user, var/company_name, var/stocks, var/shareprice, var/money)
var/datum/stock_log/L = new log_type
L.user_name = user
L.company_name = company_name
L.stocks = stocks
L.shareprice = shareprice
L.money = money
L.time = time2text(world.timeofday, "hh:mm")
logs += L
GLOBAL_DATUM_INIT(stockExchange, /datum/stockMarket, new)
/proc/plotBarGraph(var/list/points, var/base_text, var/width=400, var/height=400)
var/output = "<table style='border:1px solid black; border-collapse: collapse; width: [width]px; height: [height]px'>"
if (points.len && height > 20 && width > 20)
var/min = points[1]
var/max = points[1]
for (var/v in points)
if (v < min)
min = v
if (v > max)
max = v
var/cells = (height - 20) / 20
if (cells > round(cells))
cells = round(cells) + 1
var/diff = max - min
var/ost = diff / cells
if (min > 0)
min = max(min - ost, 0)
diff = max - min
ost = diff / cells
var/cval = max
var/cwid = width / (points.len + 1)
for (var/y = cells, y > 0, y--)
if (y == cells)
output += "<tr>"
else
output += "<tr style='border:none; border-top:1px solid #00ff00; height: 20px'>"
for (var/x = 0, x <= points.len, x++)
if (x == 0)
output += "<td style='border:none; height: 20px; width: [cwid]px; font-size:10px; color:#00ff00; background:black; text-align:right; vertical-align:bottom'>[round(cval - ost)]</td>"
else
var/v = points[x]
if (v >= cval)
output += "<td style='border:none; height: 20px; width: [cwid]px; background:#0000ff'>&nbsp;</td>"
else
output += "<td style='border:none; height: 20px; width: [cwid]px; background:black'>&nbsp;</td>"
output += "</tr>"
cval -= ost
output += "<tr><td style='font-size:10px; height: 20px; width: 100%; background:black; color:green; text-align:center' colspan='[points.len + 1]'>[base_text]</td></tr>"
else
output += "<tr><td style='width:[width]px; height:[height]px; background: black'></td></tr>"
output += "<tr><td style='font-size:10px; background:black; color:green; text-align:center'>[base_text]</td></tr>"
return "[output]</table>"
+308
View File
@@ -0,0 +1,308 @@
/datum/borrow
var/broker = ""
var/borrower = ""
var/datum/stock/stock = null
var/lease_expires = 0
var/lease_time = 0
var/grace_time = 0
var/grace_expires = 0
var/share_amount = 0
var/share_debt = 0
var/deposit = 0
var/offer_expires = 0
/datum/stock
var/name = "Stock"
var/short_name = "STK"
var/desc = "A company that does not exist."
var/list/values = list()
var/current_value = 10
var/last_value = 10
var/list/products = list()
var/performance = 0 // The current performance of the company. Tends itself to 0 when no events happen.
// These variables determine standard fluctuational patterns for this stock.
var/fluctuational_coefficient = 1 // How much the price fluctuates on an average daily basis
var/average_optimism = 0 // The history of shareholder optimism of this stock
var/current_trend = 0
var/last_trend = 0
var/speculation = 0
var/bankrupt = 0
var/disp_value_change = 0
var/optimism = 0
var/last_unification = 0
var/average_shares = 100
var/outside_shareholders = 10000 // The amount of offstation people holding shares in this company. The higher it is, the more fluctuation it causes.
var/available_shares = 500000
var/list/borrow_brokers = list()
var/list/shareholders = list()
var/list/borrows = list()
var/list/events = list()
var/list/articles = list()
var/fluctuation_rate = 15
var/fluctuation_counter = 0
var/datum/industry/industry = null
/datum/stock/proc/addEvent(var/datum/stockEvent/E)
events |= E
/datum/stock/proc/addArticle(var/datum/article/A)
if (!(A in articles))
articles.Insert(1, A)
A.ticks = world.time
/datum/stock/proc/generateEvents()
var/list/types = typesof(/datum/stockEvent) - /datum/stockEvent
for (var/T in types)
generateEvent(T)
/datum/stock/proc/generateEvent(var/T)
var/datum/stockEvent/E = new T(src)
addEvent(E)
/datum/stock/proc/affectPublicOpinion(var/boost)
optimism += rand(0, 500) / 500 * boost
average_optimism += rand(0, 150) / 5000 * boost
speculation += rand(-1, 50) / 10 * boost
performance += rand(0, 150) / 100 * boost
/datum/stock/proc/generateIndustry()
if (findtext(name, "Farms"))
industry = new /datum/industry/agriculture
else if (findtext(name, "Software") || findtext(name, "Programming") || findtext(name, "IT Group") || findtext(name, "Electronics") || findtext(name, "Electric") || findtext(name, "Nanotechnology"))
industry = new /datum/industry/it
else if (findtext(name, "Mobile") || findtext(name, "Communications"))
industry = new /datum/industry/communications
else if (findtext(name, "Pharmaceuticals") || findtext(name, "Health"))
industry = new /datum/industry/health
else if (findtext(name, "Wholesale") || findtext(name, "Stores"))
industry = new /datum/industry/consumer
else
var/ts = typesof(/datum/industry) - /datum/industry
var/in_t = pick(ts)
industry = new in_t
for (var/i = 0, i < rand(2, 5), i++)
products += industry.generateProductName(name)
/datum/stock/proc/frc(amt)
var/shares = available_shares + outside_shareholders * average_shares
var/fr = amt / 100 / shares * fluctuational_coefficient * fluctuation_rate * max(-(current_trend / 100), 1)
if ((fr < 0 && speculation < 0) || (fr > 0 && speculation > 0))
fr *= max(abs(speculation) / 5, 1)
else
fr /= max(abs(speculation) / 5, 1)
return fr
/datum/stock/proc/supplyGrowth(amt)
var/fr = frc(amt)
available_shares += amt
if (abs(fr) < 0.0001)
return
current_value -= fr * current_value
/datum/stock/proc/supplyDrop(amt)
supplyGrowth(-amt)
/datum/stock/proc/fluctuate()
var/change = rand(-100, 100) / 10 + optimism * rand(200) / 10
optimism -= (optimism - average_optimism) * (rand(10,80) / 1000)
var/shift_score = change + current_trend
var/as_score = abs(shift_score)
var/sh_change_dev = rand(-10, 10) / 10
var/sh_change = shift_score / (as_score + 100) + sh_change_dev
var/shareholder_change = round(sh_change)
outside_shareholders += shareholder_change
var/share_change = shareholder_change * average_shares
if (as_score > 20 && prob(as_score / 4))
var/avg_change_dev = rand(-10, 10) / 10
var/avg_change = shift_score / (as_score + 100) + avg_change_dev
average_shares += avg_change
share_change += outside_shareholders * avg_change
var/cv = last_value
supplyDrop(share_change)
available_shares += share_change // temporary
if (prob(25))
average_optimism = max(min(average_optimism + (rand(-3, 3) - current_trend * 0.15) / 100, 1), -1)
var/aspec = abs(speculation)
if (prob((aspec - 75) * 2))
speculation += rand(-4, 4)
else
if (prob(50))
speculation += rand(-4, 4)
else
speculation += rand(-400, 0) / 1000 * speculation
if (prob(1) && prob(5)) // pop that bubble
speculation += rand(-4000, 0) / 1000 * speculation
if (current_value < 5)
current_value = 5
if (performance != 0)
performance = rand(900,1050) / 1000 * performance
if (abs(performance) < 0.2)
performance = 0
disp_value_change = (cv < current_value) ? 1 : ((cv > current_value) ? -1 : 0)
last_value = current_value
if (values.len >= 50)
values.Cut(1,2)
values += current_value
if (current_value < 10)
unifyShares()
last_trend = current_trend
current_trend += rand(-200, 200) / 100 + optimism * rand(200) / 10 + max(50 - abs(speculation), 0) / 50 * rand(0, 200) / 1000 * (-current_trend) + max(speculation - 50, 0) * rand(0, 200) / 1000 * speculation / 400
/datum/stock/proc/unifyShares()
for (var/I in shareholders)
var/shr = shareholders[I]
if (shr % 2)
sellShares(I, 1)
shr -= 1
shareholders[I] /= 2
if (!shareholders[I])
shareholders -= I
for (var/datum/borrow/B in borrow_brokers)
B.share_amount = round(B.share_amount / 2)
B.share_debt = round(B.share_debt / 2)
for (var/datum/borrow/B in borrows)
B.share_amount = round(B.share_amount / 2)
B.share_debt = round(B.share_debt / 2)
average_shares /= 2
available_shares /= 2
current_value *= 2
last_unification = world.time
/datum/stock/process()
for (var/B in borrows)
var/datum/borrow/borrow = B
if (world.time > borrow.grace_expires)
modifyAccount(borrow.borrower, -max(current_value * borrow.share_debt, 0), 1)
borrows -= borrow
if (borrow.borrower in GLOB.FrozenAccounts)
GLOB.FrozenAccounts[borrow.borrower] -= borrow
if (length(GLOB.FrozenAccounts[borrow.borrower]) == 0)
GLOB.FrozenAccounts -= borrow.borrower
qdel(borrow)
else if (world.time > borrow.lease_expires)
if (borrow.borrower in shareholders)
var/amt = shareholders[borrow.borrower]
if (amt > borrow.share_debt)
shareholders[borrow.borrower] -= borrow.share_debt
borrows -= borrow
if (borrow.borrower in GLOB.FrozenAccounts)
GLOB.FrozenAccounts[borrow.borrower] -= borrow
if (length(GLOB.FrozenAccounts[borrow.borrower]) == 0)
GLOB.FrozenAccounts -= borrow.borrower
qdel(borrow)
else
shareholders -= borrow.borrower
borrow.share_debt -= amt
if (bankrupt)
return
for (var/B in borrow_brokers)
var/datum/borrow/borrow = B
if (borrow.offer_expires < world.time)
borrow_brokers -= borrow
qdel(borrow)
if (prob(5))
generateBrokers()
fluctuation_counter++
if (fluctuation_counter >= fluctuation_rate)
for (var/E in events)
var/datum/stockEvent/EV = E
EV.process()
fluctuation_counter = 0
fluctuate()
/datum/stock/proc/generateBrokers()
if (borrow_brokers.len > 2)
return
if (!GLOB.stockExchange.stockBrokers.len)
GLOB.stockExchange.generateBrokers()
var/broker = pick(GLOB.stockExchange.stockBrokers)
var/datum/borrow/B = new
B.broker = broker
B.stock = src
B.lease_time = rand(4, 7) * 600
B.grace_time = rand(1, 3) * 600
B.share_amount = rand(1, 10) * 100
B.deposit = rand(20, 70) / 100
B.share_debt = B.share_amount
B.offer_expires = rand(5, 10) * 600 + world.time
borrow_brokers += B
/datum/stock/proc/modifyAccount(whose, by, force=0)
if (SSsupply.points)
if (by < 0 && SSsupply.points + by < 0 && !force)
return 0
SSsupply.points += by
GLOB.stockExchange.balanceLog(whose, by)
return 1
return 0
/datum/stock/proc/borrow(var/datum/borrow/B, var/who)
if (B.lease_expires)
return 0
B.lease_expires = world.time + B.lease_time
var/old_d = B.deposit
var/d_amt = B.deposit * current_value * B.share_amount
if (!modifyAccount(who, -d_amt))
B.lease_expires = 0
B.deposit = old_d
return 0
B.deposit = d_amt
if (!(who in shareholders))
shareholders[who] = B.share_amount
else
shareholders[who] += B.share_amount
borrow_brokers -= B
borrows += B
B.borrower = who
B.grace_expires = B.lease_expires + B.grace_time
if (!(who in GLOB.FrozenAccounts))
GLOB.FrozenAccounts[who] = list(B)
else
GLOB.FrozenAccounts[who] += B
return 1
/datum/stock/proc/buyShares(var/who, var/howmany)
if (howmany <= 0)
return
howmany = round(howmany)
var/loss = howmany * current_value
if (available_shares < howmany)
return 0
if (modifyAccount(who, -loss))
supplyDrop(howmany)
if (!(who in shareholders))
shareholders[who] = howmany
else
shareholders[who] += howmany
return 1
return 0
/datum/stock/proc/sellShares(var/whose, var/howmany)
if (howmany < 0)
return
howmany = round(howmany)
var/gain = howmany * current_value
if (shareholders[whose] < howmany)
return 0
if (modifyAccount(whose, gain))
supplyGrowth(howmany)
shareholders[whose] -= howmany
if (shareholders[whose] <= 0)
shareholders -= whose
return 1
return 0
/datum/stock/proc/displayValues(var/mob/user)
user << browse(plotBarGraph(values, "[name] share value per share"), "window=stock_[name];size=450x450")
+3 -2
View File
@@ -157,11 +157,13 @@ h1.alert, h2.alert {color: #000000;}
.skrell {color: #00B0B3;}
.skrellfar {color: #70FCFF;}
.soghun {color: #50BA6C;}
.solcom {color: #22228B;}
.solcom {color: #3333CE;} /* VOREStation Edit */
.changeling {color: #800080;}
.sergal {color: #0077FF;}
.birdsongc {color: #CC9900;}
.vulpkanin {color: #B97A57;}
.tavan {color: #f54298; font-family: Arial}
.echosong {color: #826D8C;}
.enochian {color: #848A33; letter-spacing:-1pt; word-spacing:4pt; font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;}
.daemon {color: #5E339E; letter-spacing:-1pt; word-spacing:0pt; font-family: "Courier New", Courier, monospace;}
.drudakar {color: #bb2463; word-spacing:0pt; font-family: "High Tower Text", monospace;}
@@ -180,7 +182,6 @@ h1.alert, h2.alert {color: #000000;}
/* YW Edit End */
.spacer {color: #9c660b;} /* VOREStation Add */
.blob {color: #ff950d; font-weight: bold; font-style: italic;}
.tavan {color: #f54298; font-family: Arial}
.black {color: #000000;}
.darkgray {color: #808080;}
+5 -1
View File
@@ -129,6 +129,8 @@
/obj/vehicle/train/engine/turn_on()
if(!key)
return
if(!cell)
return
else
..()
update_stats()
@@ -230,7 +232,9 @@
if (on)
to_chat(usr, "You start [src]'s engine.")
else
if(cell.charge < charge_use)
if(!cell)
to_chat(usr, "[src] doesn't appear to have a power cell!")
else if(cell.charge < charge_use)
to_chat(usr, "[src] is out of power.")
else
to_chat(usr, "[src]'s engine won't start.")

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