Merge pull request #1874 from Lohikar/asteroid-gen-2

Development merge + Asteroid gen speed-up
This commit is contained in:
LordFowl
2017-03-04 20:45:24 -05:00
committed by GitHub
513 changed files with 17189 additions and 10719 deletions
+11 -15
View File
@@ -1,11 +1,11 @@
# baystation12
# Aurorastation
[Website](http://baystation12.net/) - [Code](http://github.com/Baystation12/Baystation12/) - [IRC](http://baystation12.net/forums/viewtopic.php?f=12&t=5088)
[Website](https://aurorastation.org/) - [Code](https://github.com/Aurorastation/Aurora.3)
---
### LICENSE
Baystation12 is licensed under the GNU Affero General Public License version 3, which can be found in full in LICENSE-AGPL3.txt.
Aurorastation is licensed under the GNU Affero General Public License version 3, which can be found in full in LICENSE-AGPL3.txt.
Commits with a git authorship date prior to `1420675200 +0000` (2015/01/08 00:00) are licensed under the GNU General Public License version 3, which can be found in full in LICENSE-GPL3.txt.
@@ -18,11 +18,11 @@ See [here](https://www.gnu.org/licenses/why-affero-gpl.html) for more informatio
### GETTING THE CODE
The simplest way to obtain the code is using the github .zip feature.
Click [here](https://github.com/Baystation12/Baystation12/archive/master.zip) to get the latest code as a .zip file, then unzip it to wherever you want.
Click [here](https://github.com/Aurorastation/Aurora.3/archive/master.zip) to get the latest stable code as a .zip file, then unzip it to wherever you want.
The more complicated and easier to update method is using git. You'll need to download git or some client from [here](http://git-scm.com/). When that's installed, right click in any folder and click on "Git Bash". When that opens, type in:
git clone https://github.com/Baystation12/Baystation12.git
git clone https://github.com/Aurorastation/Aurora.3.git
(hint: hold down ctrl and press insert to paste into git bash)
@@ -30,7 +30,7 @@ This will take a while to download, but it provides an easier method for updatin
Once the repository is in place, run this command:
```bash
cd Baystation12
cd Aurora.3
git update-index --assume-unchanged baystation12.int
```
Now git will ignore changes to the file baystation12.int.
@@ -45,7 +45,7 @@ This is a sourcecode-only release, so the next step is to compile the server fil
baystation12.dmb - 0 errors, 0 warnings
If you see any errors or warnings, something has gone wrong - possibly a corrupt download or the files extracted wrong, or a code issue on the main repo. Ask on IRC.
If you see any errors or warnings, something has gone wrong - possibly a corrupt download or the files extracted wrong, or a code issue on the main repo. Ask on the server Discord if you're completely lost.
Once that's done, open up the config folder. You'll want to edit config.txt to set the probabilities for different gamemodes in Secret and to set your server location so that all your players don't get disconnected at the end of each round. It's recommended you don't turn on the gamemodes with probability 0, as they have various issues and aren't currently being tested, so they may have unknown and bizarre bugs.
@@ -78,16 +78,12 @@ When you have done this, you'll need to recompile the code, but then it should w
### Configuration
For a basic setup, simply copy every file from config/example to config.
For a basic setup, simply copy every file from config/example to config.
For more advanced setups, setting the server `tick_lag` in the config as well as configuring SQL are good first steps.
---
### SQL Setup
The SQL backend for the library and stats tracking requires a MySQL server. Your server details go in /config/dbconfig.txt, and the SQL schema is in /SQL/tgstation_schema.sql. More detailed setup instructions arecoming soon, for now ask in our IRC channel.
---
### IRC Bot Setup
Included in the repo is an IRC bot capable of relaying adminhelps to a specified IRC channel/server (thanks to Skibiliano). Instructions for bot setup are included in the /bot/ folder along with the bot/relay script itself.
The SQL backend for the library and stats tracking requires a MySQL server, as does the optional SQL saves system. Your server details go in config/dbconfig.txt, and initial database setup is done with [flyway](https://flywaydb.org/). Detailed instructions can be found [here](https://github.com/Aurorastation/Aurora.3/tree/master/SQL).
+7 -6
View File
@@ -2,16 +2,17 @@
-- They are not needed for normal server operation.
CREATE TABLE `ss13dbg_lighting` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`time` INT(11) NULL DEFAULT NULL COMMENT 'World time (in ticks)',
`type` VARCHAR(32) NULL DEFAULT NULL COMMENT 'The type of the update.',
`name` VARCHAR(50) NULL DEFAULT NULL COMMENT 'The callee\'s name.',
`loc_name` VARCHAR(50) NULL DEFAULT NULL COMMENT 'The callee\'s location.',
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`time` INT(11) UNSIGNED NULL DEFAULT NULL COMMENT 'World time (in ticks)',
`tick_usage` DOUBLE UNSIGNED NULL DEFAULT NULL,
`type` VARCHAR(32) NULL DEFAULT NULL COMMENT 'The type of the update.' COLLATE 'latin1_bin',
`name` VARCHAR(50) NULL DEFAULT NULL COMMENT 'The callee\'s name.' COLLATE 'latin1_bin',
`loc_name` VARCHAR(50) NULL DEFAULT NULL COMMENT 'The callee\'s location.' COLLATE 'latin1_bin',
`x` SMALLINT(6) NULL DEFAULT NULL,
`y` SMALLINT(6) NULL DEFAULT NULL,
`z` SMALLINT(6) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
COLLATE='latin1_bin'
ENGINE=MEMORY
ROW_FORMAT=FIXED;
+50 -3
View File
@@ -29,6 +29,7 @@
#include "code\__defines\lighting.dm"
#include "code\__defines\machinery.dm"
#include "code\__defines\math_physics.dm"
#include "code\__defines\mining.dm"
#include "code\__defines\misc.dm"
#include "code\__defines\mobs.dm"
#include "code\__defines\process_scheduler.dm"
@@ -124,6 +125,7 @@
#include "code\controllers\emergency_shuttle_controller.dm"
#include "code\controllers\hooks-defs.dm"
#include "code\controllers\hooks.dm"
#include "code\controllers\law.dm"
#include "code\controllers\master_controller.dm"
#include "code\controllers\shuttle_controller.dm"
#include "code\controllers\subsystems.dm"
@@ -134,12 +136,12 @@
#include "code\controllers\Processes\arrivalShuttle.dm"
#include "code\controllers\Processes\chemistry.dm"
#include "code\controllers\Processes\disease.dm"
#include "code\controllers\Processes\effects.dm"
#include "code\controllers\Processes\emergencyShuttle.dm"
#include "code\controllers\Processes\event.dm"
#include "code\controllers\Processes\explosives.dm"
#include "code\controllers\Processes\garbage.dm"
#include "code\controllers\Processes\inactivity.dm"
#include "code\controllers\Processes\law.dm"
#include "code\controllers\Processes\lighting.dm"
#include "code\controllers\Processes\machinery.dm"
#include "code\controllers\Processes\mob.dm"
@@ -170,7 +172,6 @@
#include "code\datums\mind.dm"
#include "code\datums\mixed.dm"
#include "code\datums\modules.dm"
#include "code\datums\recipe.dm"
#include "code\datums\server_greeting.dm"
#include "code\datums\sun.dm"
#include "code\datums\supplypacks.dm"
@@ -534,10 +535,13 @@
#include "code\game\machinery\kitchen\icecream.dm"
#include "code\game\machinery\kitchen\microwave.dm"
#include "code\game\machinery\kitchen\smartfridge.dm"
#include "code\game\machinery\kitchen\cooking_machines\_appliance.dm"
#include "code\game\machinery\kitchen\cooking_machines\_cooker.dm"
#include "code\game\machinery\kitchen\cooking_machines\_cooker_output.dm"
#include "code\game\machinery\kitchen\cooking_machines\_mixer.dm"
#include "code\game\machinery\kitchen\cooking_machines\candy.dm"
#include "code\game\machinery\kitchen\cooking_machines\cereal.dm"
#include "code\game\machinery\kitchen\cooking_machines\container.dm"
#include "code\game\machinery\kitchen\cooking_machines\fryer.dm"
#include "code\game\machinery\kitchen\cooking_machines\grill.dm"
#include "code\game\machinery\kitchen\cooking_machines\oven.dm"
@@ -1172,6 +1176,11 @@
#include "code\modules\economy\Events.dm"
#include "code\modules\economy\Events_Mundane.dm"
#include "code\modules\economy\TradeDestinations.dm"
#include "code\modules\effects\effect_system.dm"
#include "code\modules\effects\visual_effect.dm"
#include "code\modules\effects\sparks\procs.dm"
#include "code\modules\effects\sparks\spawner.dm"
#include "code\modules\effects\sparks\visuals.dm"
#include "code\modules\events\apc_damage.dm"
#include "code\modules\events\bear_attack.dm"
#include "code\modules\events\blob.dm"
@@ -1223,7 +1232,10 @@
#include "code\modules\flufftext\Dreaming.dm"
#include "code\modules\flufftext\Hallucination.dm"
#include "code\modules\flufftext\TextFilters.dm"
#include "code\modules\food\recipe.dm"
#include "code\modules\food\recipes_fryer.dm"
#include "code\modules\food\recipes_microwave.dm"
#include "code\modules\food\recipes_oven.dm"
#include "code\modules\games\boardgame.dm"
#include "code\modules\games\cardemon.dm"
#include "code\modules\games\cards.dm"
@@ -1276,6 +1288,7 @@
#include "code\modules\lighting\lighting_setup.dm"
#include "code\modules\lighting\lighting_source.dm"
#include "code\modules\lighting\lighting_turf.dm"
#include "code\modules\lighting\lighting_verbs.dm"
#include "code\modules\lighting\~lighting_undefs.dm"
#include "code\modules\liquid\splash_simulation.dm"
#include "code\modules\maps\dmm_suite.dm"
@@ -1535,6 +1548,7 @@
#include "code\modules\mob\living\simple_animal\borer\say.dm"
#include "code\modules\mob\living\simple_animal\constructs\constructs.dm"
#include "code\modules\mob\living\simple_animal\constructs\soulstone.dm"
#include "code\modules\mob\living\simple_animal\familiars\familiars.dm"
#include "code\modules\mob\living\simple_animal\friendly\cat.dm"
#include "code\modules\mob\living\simple_animal\friendly\corgi.dm"
#include "code\modules\mob\living\simple_animal\friendly\crab.dm"
@@ -1562,6 +1576,9 @@
#include "code\modules\mob\living\simple_animal\hostile\syndicate.dm"
#include "code\modules\mob\living\simple_animal\hostile\tree.dm"
#include "code\modules\mob\living\simple_animal\hostile\retaliate\cavern.dm"
#include "code\modules\mob\living\simple_animal\hostile\commanded\_command_defines.dm"
#include "code\modules\mob\living\simple_animal\hostile\commanded\bear_companion.dm"
#include "code\modules\mob\living\simple_animal\hostile\commanded\commanded.dm"
#include "code\modules\mob\living\simple_animal\hostile\retaliate\clown.dm"
#include "code\modules\mob\living\simple_animal\hostile\retaliate\drone.dm"
#include "code\modules\mob\living\simple_animal\hostile\retaliate\retaliate.dm"
@@ -1755,6 +1772,7 @@
#include "code\modules\projectiles\guns\projectile.dm"
#include "code\modules\projectiles\guns\energy\laser.dm"
#include "code\modules\projectiles\guns\energy\lawgiver.dm"
#include "code\modules\projectiles\guns\energy\magic.dm"
#include "code\modules\projectiles\guns\energy\nuclear.dm"
#include "code\modules\projectiles\guns\energy\pulse.dm"
#include "code\modules\projectiles\guns\energy\rifle.dm"
@@ -1963,11 +1981,15 @@
#include "code\modules\shuttles\shuttles_multi.dm"
#include "code\modules\spells\artifacts.dm"
#include "code\modules\spells\construct_spells.dm"
#include "code\modules\spells\contracts.dm"
#include "code\modules\spells\monster_manual.dm"
#include "code\modules\spells\no_clothes.dm"
#include "code\modules\spells\spell_code.dm"
#include "code\modules\spells\spell_projectile.dm"
#include "code\modules\spells\spell_verb.dm"
#include "code\modules\spells\spellbook.dm"
#include "code\modules\spells\spells.dm"
#include "code\modules\spells\storage.dm"
#include "code\modules\spells\aoe_turf\aoe_turf.dm"
#include "code\modules\spells\aoe_turf\blink.dm"
#include "code\modules\spells\aoe_turf\charge.dm"
@@ -1977,23 +1999,48 @@
#include "code\modules\spells\aoe_turf\summons.dm"
#include "code\modules\spells\aoe_turf\conjure\conjure.dm"
#include "code\modules\spells\aoe_turf\conjure\construct.dm"
#include "code\modules\spells\aoe_turf\conjure\druidic_spells.dm"
#include "code\modules\spells\aoe_turf\conjure\forcewall.dm"
#include "code\modules\spells\aoe_turf\conjure\grove.dm"
#include "code\modules\spells\general\area_teleport.dm"
#include "code\modules\spells\general\contract_spells.dm"
#include "code\modules\spells\general\mark_recall.dm"
#include "code\modules\spells\general\return_master.dm"
#include "code\modules\spells\general\rune_write.dm"
#include "code\modules\spells\hand\hand.dm"
#include "code\modules\spells\hand\hand_item.dm"
#include "code\modules\spells\spellbook\battlemage.dm"
#include "code\modules\spells\spellbook\cleric.dm"
#include "code\modules\spells\spellbook\druid.dm"
#include "code\modules\spells\spellbook\necromancer.dm"
#include "code\modules\spells\spellbook\spatial.dm"
#include "code\modules\spells\spellbook\standard.dm"
#include "code\modules\spells\spellbook\student.dm"
#include "code\modules\spells\targeted\cleric_spells.dm"
#include "code\modules\spells\targeted\entangle.dm"
#include "code\modules\spells\targeted\ethereal_jaunt.dm"
#include "code\modules\spells\targeted\genetic.dm"
#include "code\modules\spells\targeted\harvest.dm"
#include "code\modules\spells\targeted\mind_transfer.dm"
#include "code\modules\spells\targeted\necromancer_spells.dm"
#include "code\modules\spells\targeted\shapeshift.dm"
#include "code\modules\spells\targeted\shift.dm"
#include "code\modules\spells\targeted\subjugate.dm"
#include "code\modules\spells\targeted\swap.dm"
#include "code\modules\spells\targeted\targeted.dm"
#include "code\modules\spells\targeted\torment.dm"
#include "code\modules\spells\targeted\equip\equip.dm"
#include "code\modules\spells\targeted\equip\holy_relic.dm"
#include "code\modules\spells\targeted\equip\horsemask.dm"
#include "code\modules\spells\targeted\equip\remove_horsemask.dm"
#include "code\modules\spells\targeted\equip\party_hardy.dm"
#include "code\modules\spells\targeted\equip\seed.dm"
#include "code\modules\spells\targeted\equip\shield.dm"
#include "code\modules\spells\targeted\projectile\dumbfire.dm"
#include "code\modules\spells\targeted\projectile\fireball.dm"
#include "code\modules\spells\targeted\projectile\magic_missile.dm"
#include "code\modules\spells\targeted\projectile\passage.dm"
#include "code\modules\spells\targeted\projectile\projectile.dm"
#include "code\modules\spells\targeted\projectile\stuncuff.dm"
#include "code\modules\supermatter\setup_supermatter.dm"
#include "code\modules\supermatter\supermatter.dm"
#include "code\modules\surgery\_defines.dm"
+3 -3
View File
@@ -137,13 +137,13 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
if(firelevel > 6)
icon_state = "3"
set_light(7, FIRE_LIGHT_3, update_type = UPDATE_NONE) // We set color later in the proc, that should trigger an update.
set_light(7, FIRE_LIGHT_3, no_update = TRUE) // We set color later in the proc, that should trigger an update.
else if(firelevel > 2.5)
icon_state = "2"
set_light(5, FIRE_LIGHT_2, update_type = UPDATE_NONE)
set_light(5, FIRE_LIGHT_2, no_update = TRUE)
else
icon_state = "1"
set_light(3, FIRE_LIGHT_1, update_type = UPDATE_NONE)
set_light(3, FIRE_LIGHT_1, no_update = TRUE)
for(var/mob/living/L in loc)
L.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure()) //Burn the mobs!
+11 -7
View File
@@ -1,10 +1,9 @@
#define LIGHTING_INTERVAL 1 // Frequency, in 1/10ths of a second, of the lighting process.
#define LIGHTING_INTERVAL 2 // Frequency, in 1/10ths of a second, of the lighting process.
#define LIGHTING_HEIGHT 1 // height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone
#define LIGHTING_ROUND_VALUE 1 / 128 //Value used to round lumcounts, values smaller than 1/255 don't matter (if they do, thanks sinking points), greater values will make lighting less precise, but in turn increase performance, VERY SLIGHTLY.
#define LIGHTING_ICON 'icons/effects/lighting_overlay.png' // icon used for lighting shading effects
#define DARKNESS_ICON 'icons/effects/darkness.png'
#define LIGHTING_SOFT_THRESHOLD 0.001 // If the max of the lighting lumcounts of each spectrum drops below this, disable luminosity on the lighting overlays.
@@ -52,6 +51,7 @@
#define LIGHT_COLOR_YELLOW "#E1E17D" //Dimmed yellow, leaning kaki. rgb(225, 225, 125)
#define LIGHT_COLOR_BROWN "#966432" //Clear brown, mostly dim. rgb(150, 100, 50)
#define LIGHT_COLOR_ORANGE "#FA9632" //Mostly pure orange. rgb(250, 150, 50)
#define LIGHT_COLOR_PURPLE "#A97FAA" //Soft purple. rgb(169, 127, 170)
//These ones aren't a direct colour like the ones above, because nothing would fit
#define LIGHT_COLOR_FIRE "#FAA019" //Warm orange color, leaning strongly towards yellow. rgb(250, 160, 25)
@@ -66,18 +66,22 @@
#define LIGHT_BROKEN 2
#define LIGHT_BURNED 3
// Some angle presets for directional lighting.
#define LIGHT_OMNI null
#define LIGHT_SEMI 180
#define LIGHT_WIDE 90
#define LIGHT_NARROW 45
// Night lighting controller times
// The time (in ticks based on worldtime2ticks()) that various actions trigger
#define MORNING_LIGHT_RESET 252000 // 7am or 07:00 - lighting restores to normal in morning
#define NIGHT_LIGHT_ACTIVE 648000 // 6pm or 18:00 - night lighting mode activates
// Update type flags.
#define UPDATE_SCHEDULE 0 // Default behavior. Schedule an update with lighting process.
#define UPDATE_NOW 1 // Update right now, fuck the scheduler. May cause lag.
#define UPDATE_NONE 2 // Don't trigger an update at all. Useful if you're triggering the update manually.
// Some brightness/range defines for objects.
#define L_WALLMOUNT_POWER 0.4
#define L_WALLMOUNT_RANGE 2
#define L_WALLMOUNT_HI_POWER 2 // For red/delta alert on fire alarms.
#define L_WALLMOUNT_HI_RANGE 4
// Just so we can avoid unneeded proc calls when profiling is disabled.
#define L_PROF(O,T) if (lighting_profiling) {lprof_write(O,T);}
+9
View File
@@ -96,3 +96,12 @@ var/list/restricted_camera_networks = list(NETWORK_ERT,NETWORK_MERCENARY,"Secret
#define ATMOS_DEFAULT_VOLUME_FILTER 200 // L.
#define ATMOS_DEFAULT_VOLUME_MIXER 200 // L.
#define ATMOS_DEFAULT_VOLUME_PIPE 70 // L.
// Misc process flags.
#define M_PROCESSES 0x1
#define M_USES_POWER 0x2
// If this is returned from a machine's process() proc, the machine will stop processing but
// will continue to have power calculations done.
#define M_NO_PROCESS 27
+10
View File
@@ -0,0 +1,10 @@
#define ORE_URANIUM "uranium"
#define ORE_IRON "iron"
#define ORE_COAL "coal"
#define ORE_SAND "sand"
#define ORE_PHORON "phoron"
#define ORE_SILVER "silver"
#define ORE_GOLD "gold"
#define ORE_DIAMOND "diamond"
#define ORE_PLATINUM "platinum"
#define ORE_HYDROGEN "mhydrogen"
+24
View File
@@ -269,3 +269,27 @@
#define TICK_LIMIT 80
#define TICK_CHECK ( world.tick_usage > TICK_LIMIT ? stoplag() : 0 )
#define CHECK_TICK if (world.tick_usage > TICK_LIMIT) stoplag()
// Effect Systems.
#define EFFECT_CONTINUE 0 // Keep processing.
#define EFFECT_HALT 1 // Stop processing, but don't qdel.
#define EFFECT_DESTROY 2 // qdel.
// Performance bullshit.
//supposedly the fastest way to do this according to https://gist.github.com/Giacom/be635398926bb463b42a
#define RANGE_TURFS(RADIUS, CENTER) \
block( \
locate(max(CENTER.x-(RADIUS),1), max(CENTER.y-(RADIUS),1), CENTER.z), \
locate(min(CENTER.x+(RADIUS),world.maxx), min(CENTER.y+(RADIUS),world.maxy), CENTER.z) \
)
#define get_turf(A) (get_step(A, 0))
#define QDELETED(TARGET) (!TARGET || TARGET.gcDestroyed)
//Recipe type defines. Used to determine what machine makes them
#define MICROWAVE 0x1
#define FRYER 0x2
#define OVEN 0x4
#define CANDYMAKER 0x8
#define CEREALMAKER 0x10
+4 -1
View File
@@ -133,6 +133,9 @@
set name = "Debug Pooling Type"
set category = "Debug"
if (!check_rights(R_DEBUG))
return
var/type = input("What is the typepath for the pooled object variables you wish to view?", "Pooled Variables") in pooledvariables|null
if(!type)
@@ -149,4 +152,4 @@
// Shim - this method doesn't natively exist in this implementation.
/proc/IsPooled(var/datum/D)
return "[D.type]" in masterdatumPool
return "[D.type]" in masterdatumPool
-1
View File
@@ -631,7 +631,6 @@ proc/ColorTone(rgb, tone)
/*
Get flat icon by DarkCampainger. As it says on the tin, will return an icon with all the overlays
as a single icon. Useful for when you want to manipulate an icon via the above as overlays are not normally included.
The _flatIcons list is a cache for generated icon files.
*/
proc // Creates a single icon from a given /atom or /image. Only the first argument is required.
+9 -1
View File
@@ -127,4 +127,12 @@
return (val & (val-1)) == 0
/proc/RoundUpToPowerOfTwo(var/val)
return 2 ** -round(-log(2,val))
return 2 ** -round(-log(2,val))
//Written by Lohikar
//Returns the cube root of the input number
/proc/cubert(var/num, var/iterations = 10)
. = num
for (var/i = 0, i < iterations, i++)
. = (1/3) * (num/(.**2)+2*.)
+22
View File
@@ -180,6 +180,28 @@
if(start)
return findtextEx(text, suffix, start, null)
//Parses a string into a list
/proc/dd_text2List(text, separator)
var/textlength = lentext(text)
var/separatorlength = lentext(separator)
var/list/textList = new /list()
var/searchPosition = 1
var/findPosition = 1
var/buggyText
while (1) // Loop forever.
findPosition = findtextEx(text, separator, searchPosition, 0)
buggyText = copytext(text, searchPosition, findPosition) // Everything from searchPosition to findPosition goes into a list element.
textList += "[buggyText]" // Working around weird problem where "text" != "text" after this copytext().
searchPosition = findPosition + separatorlength // Skip over separator.
if (findPosition == 0) // Didn't find anything at end of string so stop here.
return textList
else
if (searchPosition > textlength) // Found separator at very end of string.
textList += "" // So add empty element
/*
* Text modification
*/
-7
View File
@@ -1065,13 +1065,6 @@ proc/get_mob_with_client_list()
else if (zone == "r_foot") return "right foot"
else return zone
//gets the turf the atom is located in (or itself, if it is a turf).
//returns null if the atom is not in a turf.
/proc/get_turf(atom/A)
if(!istype(A)) return
for(A, A && !isturf(A), A=A.loc);
return A
/proc/get(atom/loc, type)
while(loc)
if(istype(loc, type))
@@ -125,6 +125,7 @@
/obj/screen/movable/spell_master/proc/silence_spells(var/amount)
for(var/obj/screen/spell/spell in spell_objects)
spell.spell.silenced = amount
spell.spell.process()
spell.update_charge(1)
/obj/screen/movable/spell_master/proc/update_spells(forced = 0, mob/user)
+1 -3
View File
@@ -110,9 +110,7 @@
M.Stun(power)
M.stuttering = max(M.stuttering, power)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, M)
s.start()
spark(M, 5, alldirs)
if(prob(stunprob) && powerlevel >= 8)
M.adjustFireLoss(powerlevel * rand(6,10))
+92
View File
@@ -0,0 +1,92 @@
#define STAGE_IDLE 0
#define STAGE_EFFECT 1
#define STAGE_SUBEFFECT 2
var/datum/controller/process/effects/effect_master
/var/list/datum/effect_system/effects_objects = list() // The effect-spawning objects. Shouldn't be many of these.
/var/list/obj/visual_effect/effects_visuals = list() // The visible component of an effect. May be created without an effect object.
/datum/controller/process/effects
var/tmp/list/processing_effects = list()
var/tmp/list/processing_visuals = list()
var/tmp/stage = STAGE_IDLE
/datum/controller/process/effects/setup()
effect_master = src
name = "effects"
schedule_interval = 2
tick_allowance = 15
/datum/controller/process/effects/doWork()
if (stage == STAGE_IDLE)
// Start a new work cycle.
processing_effects = effects_objects
effects_objects = list()
stage = STAGE_EFFECT
while (processing_effects.len)
var/datum/effect_system/E = processing_effects[processing_effects.len]
processing_effects.len--
if (!E || E.gcDestroyed)
continue
switch (E.process())
if (EFFECT_CONTINUE)
effects_objects += E
if (EFFECT_DESTROY)
qdel(E)
F_SCHECK
if (stage == STAGE_EFFECT)
processing_visuals = effects_visuals
effects_visuals = list()
stage = STAGE_SUBEFFECT
while (processing_visuals.len)
var/obj/visual_effect/V = processing_visuals[processing_visuals.len]
processing_visuals.len--
if (!V || V.gcDestroyed)
effects_visuals -= V
continue
switch (V.tick())
if (EFFECT_CONTINUE)
effects_visuals += V
if (EFFECT_DESTROY)
effects_visuals -= V
V.end()
qdel(V)
F_SCHECK
stage = STAGE_IDLE
// We're done.
if (!processing_effects.len && !processing_visuals.len && !effects_objects.len && !effects_visuals.len)
disable()
/datum/controller/process/effects/proc/queue(var/datum/effect_system/E)
if (!E || E.gcDestroyed)
return
effects_objects += E
enable()
/datum/controller/process/effects/proc/queue_simple(var/obj/visual_effect/V)
if (!V || V.gcDestroyed)
return
effects_visuals += V
enable()
/datum/controller/process/effects/statProcess()
..()
stat(null, "Effect process is [disabled ? "sleeping" : "processing"].")
stat(null, "[effects_objects.len] effects queued, [processing_effects.len] processing")
stat(null, "[effects_visuals.len] visuals queued, [processing_visuals.len] processing")
-5
View File
@@ -127,11 +127,6 @@ world/loop_checks = 0
stat(null, "[garbage_collect ? "On" : "Off"], [destroyed.len] queued")
stat(null, "Dels: [total_dels], [soft_dels] soft, [hard_dels] hard, [tick_dels] last run")
// Tests if an atom has been deleted.
/proc/deleted(atom/A)
return !A || !isnull(A.gcDestroyed)
// Should be treated as a replacement for the 'del' keyword.
// Datums passed to this will be given a chance to clean up references to allow the GC to collect them.
/proc/qdel(var/datum/A)
-30
View File
@@ -1,30 +0,0 @@
/var/global/datum/controller/process/law/corp_regs
/datum/controller/process/law
var/list/laws = list() // All laws
var/list/low_severity = list()
var/list/med_severity = list()
var/list/high_severity = list()
disabled = 1
/datum/controller/process/law/New()
corp_regs = src
..()
/datum/controller/process/law/setup()
name = "Law"
schedule_interval = 100
for( var/L in subtypesof( /datum/law/low_severity ))
low_severity += new L
for( var/L in subtypesof( /datum/law/med_severity ))
med_severity += new L
for( var/L in subtypesof( /datum/law/high_severity ))
high_severity += new L
laws = low_severity + med_severity + high_severity
+8 -30
View File
@@ -14,36 +14,29 @@
/datum/controller/process/lighting
schedule_interval = LIGHTING_INTERVAL
var/list/curr_lights = list()
var/list/curr_corners = list()
var/list/curr_overlays = list()
var/list/resume_pos = 0
/datum/controller/process/lighting/setup()
name = "lighting"
lighting_process = src
/datum/controller/process/lighting/statProcess()
..()
stat(null, "Server tick usage is [world.tick_usage].")
stat(null, "[all_lighting_overlays.len] overlays ([all_lighting_corners.len] corners)")
stat(null, "Lights: [lighting_update_lights.len] queued, [curr_lights.len] processing")
stat(null, "Corners: [lighting_update_corners.len] queued, [curr_corners.len] processing")
stat(null, "Overlays: [lighting_update_overlays.len] queued, [curr_overlays.len] processing")
stat(null, "Lights: [lighting_update_lights.len] queued")
stat(null, "Corners: [lighting_update_corners.len] queued")
stat(null, "Overlays: [lighting_update_overlays.len] queued")
/datum/controller/process/lighting/doWork()
// -- SOURCES --
if (resume_pos == STAGE_NONE)
curr_lights = lighting_update_lights
lighting_update_lights = list()
resume_pos = STAGE_SOURCE
var/list/curr_lights = lighting_update_lights
var/list/curr_corners = lighting_update_corners
var/list/curr_overlays = lighting_update_overlays
while (curr_lights.len)
var/datum/light_source/L = curr_lights[curr_lights.len]
curr_lights.len--
if(L.check() || L.destroyed || L.force_update)
if(L.destroyed || L.check() || L.force_update)
L.remove_lum()
if(!L.destroyed)
L.apply_lum()
@@ -57,13 +50,6 @@
F_SCHECK
// -- CORNERS --
if (resume_pos == STAGE_SOURCE)
curr_corners = lighting_update_corners
lighting_update_corners = list()
resume_pos = STAGE_CORNER
while (curr_corners.len)
var/datum/lighting_corner/C = curr_corners[curr_corners.len]
curr_corners.len--
@@ -74,12 +60,6 @@
F_SCHECK
if (resume_pos == STAGE_CORNER)
curr_overlays = lighting_update_overlays
lighting_update_overlays = list()
resume_pos = STAGE_OVERLAY
while (curr_overlays.len)
var/atom/movable/lighting_overlay/O = curr_overlays[curr_overlays.len]
curr_overlays.len--
@@ -89,8 +69,6 @@
F_SCHECK
resume_pos = 0
#undef STAGE_NONE
#undef STAGE_SOURCE
#undef STAGE_CORNER
+65 -21
View File
@@ -1,16 +1,39 @@
/var/global/machinery_sort_required = 0
/var/global/machinery_sort_required = 0
var/global/list/power_using_machines = list()
var/global/list/ticking_machines = list()
#define STAGE_NONE 0
#define STAGE_MACHINERY 1
#define STAGE_POWERNET 2
#define STAGE_POWERSINK 3
#define STAGE_PIPENET 4
#define STAGE_MACHINERY_PROCESS 1
#define STAGE_MACHINERY_POWER 2
#define STAGE_POWERNET 3
#define STAGE_POWERSINK 4
#define STAGE_PIPENET 5
/proc/add_machine(var/obj/machinery/M)
if (QDELETED(M))
return
var/type = M.get_process_type()
if (type)
machines += M
if (type & M_PROCESSES)
ticking_machines += M
if (type & M_USES_POWER)
power_using_machines += M
/proc/remove_machine(var/obj/machinery/M)
machines -= M
power_using_machines -= M
ticking_machines -= M
/datum/controller/process/machinery
var/tmp/list/processing_machinery = list()
var/tmp/list/processing_powernets = list()
var/tmp/list/processing_powersinks = list()
var/tmp/list/processing_pipenets = list()
var/tmp/list/processing_machinery = list()
var/tmp/list/processing_power_users = list()
var/tmp/list/processing_powernets = list()
var/tmp/list/processing_powersinks = list()
var/tmp/list/processing_pipenets = list()
var/stage = STAGE_NONE
/datum/controller/process/machinery/setup()
@@ -21,20 +44,37 @@
/datum/controller/process/machinery/doWork()
// If we're starting a new tick, setup.
if (stage == STAGE_NONE)
processing_machinery = machines.Copy()
stage = STAGE_MACHINERY
processing_machinery = ticking_machines.Copy()
stage = STAGE_MACHINERY_PROCESS
// Process machinery.
while (processing_machinery.len)
var/obj/machinery/M = processing_machinery[processing_machinery.len]
processing_machinery.len--
if (!M || M.gcDestroyed)
machines -= M
if (QDELETED(M))
remove_machine(M)
continue
if (M.process() == PROCESS_KILL)
machines -= M
switch (M.process())
if (PROCESS_KILL)
remove_machine(M)
if (M_NO_PROCESS)
ticking_machines -= M
F_SCHECK
if (stage == STAGE_MACHINERY_PROCESS)
processing_power_users = power_using_machines.Copy()
stage = STAGE_MACHINERY_POWER
while (processing_power_users.len)
var/obj/machinery/M = processing_power_users[processing_power_users.len]
processing_power_users.len--
if (QDELETED(M))
remove_machine(M)
continue
if (M.use_power)
@@ -42,7 +82,7 @@
F_SCHECK
if (stage == STAGE_MACHINERY)
if (stage == STAGE_MACHINERY_POWER)
processing_powernets = powernets.Copy()
stage = STAGE_POWERNET
@@ -50,7 +90,7 @@
var/datum/powernet/PN = processing_powernets[processing_powernets.len]
processing_powernets.len--
if (!PN || PN.gcDestroyed)
if (QDELETED(PN))
powernets -= PN
continue
@@ -65,7 +105,7 @@
var/obj/item/I = processing_powersinks[processing_powersinks.len]
processing_powersinks.len--
if (!I || !I.pwr_drain())
if (QDELETED(I) || !I.pwr_drain())
processing_power_items -= I
F_SCHECK
@@ -78,7 +118,8 @@
var/datum/pipe_network/PN = processing_pipenets[processing_pipenets.len]
processing_pipenets.len--
if (!PN || PN.gcDestroyed)
if (QDELETED(PN))
pipe_networks -= PN
continue
PN.process()
@@ -93,13 +134,16 @@
/datum/controller/process/machinery/statProcess()
..()
stat(null, "[machines.len] machines, [processing_machinery.len] queued")
stat(null, "[machines.len] total machines")
stat(null, "[ticking_machines.len] ticking machines, [processing_machinery.len] queued")
stat(null, "[power_using_machines.len] power-using machines, [processing_power_users.len] queued")
stat(null, "[powernets.len] powernets, [processing_powernets.len] queued")
stat(null, "[processing_power_items.len] power items, [processing_powersinks.len] queued")
stat(null, "[pipe_networks.len] pipenets, [processing_pipenets.len] queued")
#undef STAGE_NONE
#undef STAGE_MACHINERY
#undef STAGE_MACHINERY_PROCESS
#undef STAGE_MACHINERY_POWER
#undef STAGE_POWERNET
#undef STAGE_POWERSINK
#undef STAGE_PIPENET
+5 -4
View File
@@ -10,7 +10,7 @@
/datum/controller/process/scheduler/setup()
name = "scheduler"
schedule_interval = 3 SECONDS
schedule_interval = 2 SECONDS
scheduled_tasks = list()
scheduler = src
@@ -23,13 +23,14 @@
var/datum/scheduled_task/task = queued_tasks[queued_tasks.len]
queued_tasks.len--
if (QDELETED(task))
scheduled_tasks -= task
continue
if (world.time > task.trigger_time)
unschedule(task)
// why are these separated.
task.pre_process()
F_SCHECK // fuck it, it's a cheap call.
task.process()
F_SCHECK
task.post_process()
F_SCHECK
+4
View File
@@ -103,6 +103,7 @@ var/list/gamemode_cache = list()
var/banappeals
var/wikiurl
var/forumurl
var/forum_passphrase
var/githuburl
//Alert level description
@@ -458,6 +459,9 @@ var/list/gamemode_cache = list()
if ("forumurl")
config.forumurl = value
if ("forum_passphrase")
config.forum_passphrase = value
if ("githuburl")
config.githuburl = value
+24
View File
@@ -0,0 +1,24 @@
/var/global/datum/controller/law/corp_regs
/datum/controller/law
var/list/laws = list() // All laws
var/list/low_severity = list()
var/list/med_severity = list()
var/list/high_severity = list()
/datum/controller/law/New()
corp_regs = src
for (var/L in subtypesof(/datum/law/low_severity))
low_severity += new L
for (var/L in subtypesof(/datum/law/med_severity))
med_severity += new L
for (var/L in subtypesof(/datum/law/high_severity))
high_severity += new L
laws = low_severity + med_severity + high_severity
..()
+7 -6
View File
@@ -81,6 +81,7 @@ datum/controller/game_controller/proc/setup_objects()
admin_notice(span("danger", "Done."))
if(config.generate_asteroid)
var/time = world.time
// These values determine the specific area that the map is applied to.
// If you do not use the official Baycode moonbase map, you will need to change them.
//Create the mining Z-level.
@@ -92,12 +93,9 @@ datum/controller/game_controller/proc/setup_objects()
new /datum/random_map/noise/ore(null, 0, 0, 5, 64, 64)
new /datum/random_map/noise/ore(null, 0, 0, 4, 64, 64)
new /datum/random_map/noise/ore(null, 0, 0, 3, 64, 64)
// Update all turfs to ensure everything looks good post-generation. Yes,
// it's brute-forcey, but frankly the alternative is a mine turf rewrite.
for(var/turf/simulated/mineral/M in world) // Ugh.
M.updateMineralOverlays()
for(var/turf/simulated/floor/asteroid/M in world) // Uuuuuugh.
M.updateMineralOverlays()
var/msg = "Asteroid generation completed in [(world.time - time) / 10] seconds."
admin_notice(span("danger", msg))
game_log("ASGEN", msg)
admin_notice(span("danger", "Setting up lighting."))
initialize_lighting()
@@ -113,5 +111,8 @@ datum/controller/game_controller/proc/setup_objects()
//Set up spawn points.
populate_spawn_points()
// Setup laws.
global.corp_regs = new
admin_notice("<span class='danger'>Initializations complete.</span>", R_DEBUG)
sleep(-1)
+6 -7
View File
@@ -7,8 +7,8 @@
var/atom/movable/teleatom //atom to teleport
var/atom/destination //destination to teleport to
var/precision = 0 //teleport precision
var/datum/effect/effect/system/effectin //effect to show right before teleportation
var/datum/effect/effect/system/effectout //effect to show right after teleportation
var/datum/effect_system/effectin //effect to show right before teleportation
var/datum/effect_system/effectout //effect to show right after teleportation
var/soundin //soundfile to play before teleportation
var/soundout //soundfile to play after teleportation
var/force_teleport = 1 //if false, teleport will use Move() proc (dense objects will prevent teleportation)
@@ -78,13 +78,13 @@
/datum/teleport/proc/teleportChecks()
return 1
/datum/teleport/proc/playSpecials(atom/location,datum/effect/effect/system/effect,sound)
/datum/teleport/proc/playSpecials(atom/location,datum/effect_system/effect,sound)
if(location)
if(effect)
spawn(-1)
src = null
effect.attach(location)
effect.start()
effect.location = location
effect.queue()
if(sound)
spawn(-1)
src = null
@@ -141,8 +141,7 @@
/datum/teleport/instant/science/setEffects(datum/effect/effect/system/aeffectin,datum/effect/effect/system/aeffectout)
if(!aeffectin || !aeffectout)
var/datum/effect/effect/system/spark_spread/aeffect = new
aeffect.set_up(5, 1, teleatom)
var/datum/effect_system/sparks/aeffect = getFromPool(/datum/effect_system/sparks, null, FALSE, 5, alldirs)
effectin = effectin || aeffect
effectout = effectout || aeffect
return 1
-136
View File
@@ -1,136 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * *
* /datum/recipe by rastaf0 13 apr 2011 *
* * * * * * * * * * * * * * * * * * * * * * * * * *
* This is powerful and flexible recipe system.
* It exists not only for food.
* supports both reagents and objects as prerequisites.
* In order to use this system you have to define a deriative from /datum/recipe
* * reagents are reagents. Acid, milc, booze, etc.
* * items are objects. Fruits, tools, circuit boards.
* * result is type to create as new object
* * time is optional parameter, you shall use in in your machine,
default /datum/recipe/ procs does not rely on this parameter.
*
* Functions you need:
* /datum/recipe/proc/make(var/obj/container as obj)
* Creates result inside container,
* deletes prerequisite reagents,
* transfers reagents from prerequisite objects,
* deletes all prerequisite objects (even not needed for recipe at the moment).
*
* /proc/select_recipe(list/datum/recipe/avaiable_recipes, obj/obj as obj, exact = 1)
* Wonderful function that select suitable recipe for you.
* obj is a machine (or magik hat) with prerequisites,
* exact = 0 forces algorithm to ignore superfluous stuff.
*
*
* Functions you do not need to call directly but could:
* /datum/recipe/proc/check_reagents(var/datum/reagents/avail_reagents)
* /datum/recipe/proc/check_items(var/obj/container as obj)
*
* */
/datum/recipe
var/list/reagents // example: = list("berryjuice" = 5) // do not list same reagent twice
var/list/items // example: = list(/obj/item/weapon/crowbar, /obj/item/weapon/welder) // place /foo/bar before /foo
var/list/fruit // example: = list("fruit" = 3)
var/result // example: = /obj/item/weapon/reagent_containers/food/snacks/donut/normal
var/time = 100 // 1/10 part of second
/datum/recipe/proc/check_reagents(var/datum/reagents/avail_reagents)
. = 1
for (var/r_r in reagents)
var/aval_r_amnt = avail_reagents.get_reagent_amount(r_r)
if (!(abs(aval_r_amnt - reagents[r_r])<0.5)) //if NOT equals
if (aval_r_amnt>reagents[r_r])
. = 0
else
return -1
if ((reagents?(reagents.len):(0)) < avail_reagents.reagent_list.len)
return 0
return .
/datum/recipe/proc/check_fruit(var/obj/container)
. = 1
if(fruit && fruit.len)
var/list/checklist = list()
// You should trust Copy().
checklist = fruit.Copy()
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in container)
if(!G.seed || !G.seed.kitchen_tag || isnull(checklist[G.seed.kitchen_tag]))
continue
checklist[G.seed.kitchen_tag]--
for(var/ktag in checklist)
if(!isnull(checklist[ktag]))
if(checklist[ktag] < 0)
. = 0
else if(checklist[ktag] > 0)
. = -1
break
return .
/datum/recipe/proc/check_items(var/obj/container as obj)
. = 1
if (items && items.len)
var/list/checklist = list()
checklist = items.Copy() // You should really trust Copy
for(var/obj/O in container)
if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown))
continue // Fruit is handled in check_fruit().
var/found = 0
for(var/i = 1; i < checklist.len+1; i++)
var/item_type = checklist[i]
if (istype(O,item_type))
checklist.Cut(i, i+1)
found = 1
break
if (!found)
. = 0
if (checklist.len)
. = -1
return .
//general version
/datum/recipe/proc/make(var/obj/container as obj)
var/obj/result_obj = new result(container)
for (var/obj/O in (container.contents-result_obj))
O.reagents.trans_to_obj(result_obj, O.reagents.total_volume)
qdel(O)
container.reagents.clear_reagents()
return result_obj
// food-related
/datum/recipe/proc/make_food(var/obj/container as obj)
if(!result)
world << "<span class='danger'>Recipe [type] is defined without a result, please bug this.</span>"
return
var/obj/result_obj = new result(container)
for (var/obj/O in (container.contents-result_obj))
if (O.reagents)
O.reagents.del_reagent("nutriment")
O.reagents.update_total()
O.reagents.trans_to_obj(result_obj, O.reagents.total_volume)
qdel(O)
container.reagents.clear_reagents()
return result_obj
/proc/select_recipe(var/list/datum/recipe/avaiable_recipes, var/obj/obj as obj, var/exact)
var/list/datum/recipe/possible_recipes = new
var/target = exact ? 0 : 1
for (var/datum/recipe/recipe in avaiable_recipes)
if((recipe.check_reagents(obj.reagents) < target) || (recipe.check_items(obj) < target) || (recipe.check_fruit(obj) < target))
continue
possible_recipes |= recipe
if (possible_recipes.len==0)
return null
else if (possible_recipes.len==1)
return possible_recipes[1]
else //okay, let's select the most complicated recipe
var/highest_count = 0
. = possible_recipes[1]
for (var/datum/recipe/recipe in possible_recipes)
var/count = ((recipe.items)?(recipe.items.len):0) + ((recipe.reagents)?(recipe.reagents.len):0) + ((recipe.fruit)?(recipe.fruit.len):0)
if (count >= highest_count)
highest_count = count
. = recipe
return .
+10 -1
View File
@@ -15,8 +15,17 @@
item_cost = round(DEFAULT_TELECRYSTAL_AMOUNT / 2)
desc = "Causes a falsified [command_name()] Update. Triggers immediately after supplying additional data."
/datum/uplink_item/abstract/announcements/fake_centcom/extra_args(var/mob/user)
var/title = sanitize(input("Enter your announcement title.", "Announcement Title") as null|text)
if(!title)
return
var/message = sanitize(input("Enter your announcement message.", "Announcement Title") as null|text)
if(!message)
return
return list("title" = title, "message" = message)
/datum/uplink_item/abstract/announcements/fake_centcom/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/user, var/list/args)
command_announcement.Announce(args.["message"], args.["title"])
command_announcement.Announce(args["message"], args["title"])
return 1
/datum/uplink_item/abstract/announcements/fake_crew_arrival
+6
View File
@@ -9,6 +9,12 @@
item_cost = 2
path = /obj/item/weapon/storage/toolbox/syndicate
/datum/uplink_item/item/tools/advancedpinpointer
name = "Advanced pinpointer"
item_cost = 15
path = /obj/item/weapon/pinpointer/advpinpointer
desc = "An advanced pinpointer that can find any target with DNA along with various other items."
/datum/uplink_item/item/tools/money
name = "Operations Funding"
item_cost = 2
+6 -1
View File
@@ -47,6 +47,9 @@ var/datum/uplink/uplink = new()
if(!can_buy(U))
return
if(U.CanUseTopic(user, inventory_state) != STATUS_INTERACTIVE)
return
var/cost = cost(U.uses)
var/goods = get_goods(U, get_turf(user), user, extra_args)
@@ -143,7 +146,9 @@ datum/uplink_item/dd_SortValue()
* Abstract Uplink Entries *
* *
********************************/
var/image/default_abstract_uplink_icon
/datum/uplink_item/abstract
var/static/image/default_abstract_uplink_icon
/datum/uplink_item/abstract/log_icon()
if(!default_abstract_uplink_icon)
default_abstract_uplink_icon = image('icons/obj/pda.dmi', "pda-syn")
+12 -11
View File
@@ -173,7 +173,7 @@
throw_range = 5
w_class = 2.0
attack_verb = list("warned", "cautioned", "smashed")
/obj/item/weapon/caution/attack_self(mob/user as mob)
if(src.icon_state == "caution")
src.icon_state = "caution_blinking"
@@ -181,14 +181,15 @@
else
src.icon_state = "caution"
user << "You turn the sign off."
/obj/item/weapon/caution/AltClick()
if(src.icon_state == "caution")
src.icon_state = "caution_blinking"
usr << "You turn the sign on."
else
src.icon_state = "caution"
usr << "You turn the sign off."
if(!usr || usr.stat || usr.lying || usr.restrained() || !Adjacent(usr)) return
if(src.icon_state == "caution")
src.icon_state = "caution_blinking"
usr << "You turn the sign on."
else
src.icon_state = "caution"
usr << "You turn the sign off."
/obj/item/weapon/caution/cone
desc = "This cone is trying to warn you of something!"
@@ -197,10 +198,10 @@
item_state = "cone"
contained_sprite = 1
slot_flags = SLOT_HEAD
/obj/item/weapon/caution/cone/attack_self(mob/user as mob)
return
/obj/item/weapon/caution/cone/AltClick()
return
@@ -427,7 +428,7 @@
icon = 'icons/obj/stock_parts.dmi'
w_class = 2.0
var/rating = 1
/obj/item/weapon/stock_parts/New()
src.pixel_x = rand(-5.0, 5)
src.pixel_y = rand(-5.0, 5)
+1
View File
@@ -14,6 +14,7 @@ var/datum/antagonist/xenos/xenomorphs
faction_descriptor = "Hive"
faction_welcome = "Your will is ripped away as your humanity merges with the xenomorph overmind. You are now \
a thrall to the queen and her brood. Obey their instructions without question. Serve the hive."
faction = "xenomorph"
hard_cap = 5
hard_cap_round = 8
+1
View File
@@ -30,6 +30,7 @@
var/faction_descriptor // Description of the cause. Mandatory for faction role.
var/faction_verb // Verb added when becoming a member of the faction, if any.
var/faction_welcome // Message shown to faction members.
var/faction = "neutral" // Faction name, mostly used for simple animals.
// Spawn values (autotraitor and game mode)
var/hard_cap = 3 // Autotraitor var. Won't spawn more than this many antags.
+3
View File
@@ -14,6 +14,9 @@
create_antagonist(player, move_to_spawn, do_not_announce, preserve_appearance)
if(!do_not_equip)
equip(player.current)
player.current.faction = faction
return 1
/datum/antagonist/proc/add_antagonist_mind(var/datum/mind/player, var/ignore_role, var/nonstandard_role_type, var/nonstandard_role_msg)
+2 -1
View File
@@ -9,9 +9,10 @@
player.drop_from_inventory(thing)
if(thing.loc != player)
qdel(thing)
player.species.equip_survival_gear(player)
return 1
/datum/antagonist/proc/unequip(var/mob/living/carbon/human/player)
if(!istype(player))
return 0
return 1
return 1
@@ -3,6 +3,10 @@
set category = "Abilities"
if(!M.mind)
return
for (var/obj/item/weapon/implant/loyalty/I in M)
if (I.implanted)
src << "<span class='warning'>[M] is too loyal to the company!</span>"
return
convert_to_faction(M.mind, revs)
/mob/living/proc/convert_to_faction(var/datum/mind/player, var/datum/antagonist/faction)
+1 -1
View File
@@ -30,7 +30,7 @@ var/datum/antagonist/ert/ert
/datum/antagonist/ert/greet(var/datum/mind/player)
if(!..())
return
player.current << "The Emergency Response Team works for Asset Protection; your job is to protect NanoTrasen's assets. There is a code red alert on [station_name()], you are tasked to go and fix the problem."
player.current << "The Emergency Response Team works for Asset Protection; your job is to protect [company_name]'s assets. There is a code red alert on [station_name()], you are tasked to go and fix the problem."
player.current << "You should first gear up and discuss a plan with your team. More members may be joining, don't move out before you're ready."
/datum/antagonist/ert/equip(var/mob/living/carbon/human/player)
+23 -5
View File
@@ -14,7 +14,8 @@ var/datum/antagonist/wizard/wizards
hard_cap_round = 3
initial_spawn_req = 1
initial_spawn_target = 1
faction = "Space Wizard"
/datum/antagonist/wizard/New()
..()
@@ -85,7 +86,8 @@ var/datum/antagonist/wizard/wizards
if(wizard_mob.backbag == 5) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/duffel/wizard(wizard_mob), slot_back)
wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box(wizard_mob), slot_in_backpack)
wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(wizard_mob), slot_r_store)
wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/spellbook(wizard_mob), slot_r_hand)
var/obj/item/I = new /obj/item/weapon/spellbook(get_turf(wizard_mob))
wizard_mob.put_in_hands(I)
wizard_mob.update_icons()
return 1
@@ -100,6 +102,22 @@ var/datum/antagonist/wizard/wizards
feedback_set_details("round_end_result","loss - wizard killed")
world << "<span class='danger'><font size = 3>The [(current_antagonists.len>1)?"[role_text_plural] have":"[role_text] has"] been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!</font></span>"
/datum/antagonist/wizard/print_player_summary()
..()
for(var/p in current_antagonists)
var/datum/mind/player = p
var/text = "<b>[player.name]'s spells were:</b>"
if(!player.learned_spells || !player.learned_spells.len)
text += "<br>None!"
else
for(var/s in player.learned_spells)
var/spell/spell = s
text += "<br><b>[spell.name]</b> - "
text += "Speed: [spell.spell_levels["speed"]] Power: [spell.spell_levels["power"]]"
text += "<br>"
world << text
//To batch-remove wizard spells. Linked to mind.dm.
/mob/proc/spellremove()
for(var/spell/spell_to_remove in src.spell_list)
@@ -120,13 +138,13 @@ Made a proc so this is not repeated 14 (or more) times.*/
// Humans can wear clothes.
/mob/living/carbon/human/wearing_wiz_garb()
if(!is_wiz_garb(src.wear_suit))
if(!is_wiz_garb(src.wear_suit) && (!src.species.hud || (slot_wear_suit in src.species.hud.equip_slots)))
src << "<span class='warning'>I don't feel strong enough without my robe.</span>"
return 0
if(!is_wiz_garb(src.shoes))
if(!is_wiz_garb(src.shoes) && (!species.hud || (slot_shoes in src.species.hud.equip_slots)))
src << "<span class='warning'>I don't feel strong enough without my sandals.</span>"
return 0
if(!is_wiz_garb(src.head))
if(!is_wiz_garb(src.head) && (!species.hud || (slot_head in src.species.hud.equip_slots)))
src << "<span class='warning'>I don't feel strong enough without my hat.</span>"
return 0
return 1
+5 -1
View File
@@ -104,12 +104,16 @@ var/datum/antagonist/cultist/cult
player.memory = ""
if(show_message)
player.current.visible_message("<FONT size = 3>[player.current] looks like they just reverted to their old faith!</FONT>")
if(. && player.current && !istype(player.current, /mob/living/simple_animal/construct))
player.current.remove_language(LANGUAGE_CULT)
/datum/antagonist/cultist/add_antagonist(var/datum/mind/player)
. = ..()
if(.)
player << "You catch a glimpse of the Realm of Nar-Sie, the Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of That Which Waits. Assist your new compatriots in their dark dealings. Their goals are yours, and yours are theirs. You serve the Dark One above all else. Bring It back."
if(player.current && !istype(player.current, /mob/living/simple_animal/construct))
player.current.add_language(LANGUAGE_CULT)
/datum/antagonist/cultist/can_become_antag(var/datum/mind/player, ignore_role = 1)
if(!..())
return 0
+10 -2
View File
@@ -28,8 +28,8 @@ var/datum/antagonist/revolutionary/revs
faction_indicator = "rev"
faction_invisible = 1
restricted_jobs = list("Internal Affairs Agent", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
protected_jobs = list("Security Officer", "Warden", "Detective")
restricted_jobs = list("AI", "Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Personnel", "Chief Engineer", "Research Director", "Chief Medical Officer", "Captain", "Head of Security", "Internal Affairs Agent")
/datum/antagonist/revolutionary/New()
..()
@@ -46,3 +46,11 @@ var/datum/antagonist/revolutionary/revs
rev_obj.target = player.mind
rev_obj.explanation_text = "Assassinate, capture or convert [player.real_name], the [player.mind.assigned_role]."
global_objectives += rev_obj
/datum/antagonist/revolutionary/can_become_antag(var/datum/mind/player)
if(!..())
return 0
for(var/obj/item/weapon/implant/loyalty/L in player.current)
if(L && (L.imp_in == player.current))
return 0
return 1
+2 -2
View File
@@ -2,8 +2,8 @@ var/datum/antagonist/thrall/vampire_thrall = null
/datum/antagonist/thrall
id = MODE_THRALL
role_text = "thrall"
role_text_plural = "thralls"
role_text = "Thrall"
role_text_plural = "Thralls"
bantype = "vampires"
feedback_tag = "thrall_objective"
restricted_jobs = list("AI", "Cyborg", "Chaplain")
+3 -1
View File
@@ -256,7 +256,6 @@ area/space/atmosalert()
/area/shuttle/mining/outpost
icon_state = "shuttle"
base_turf = /turf/simulated/floor/asteroid
/area/shuttle/transport1/centcom
icon_state = "shuttle"
@@ -556,6 +555,7 @@ area/space/atmosalert()
/area/syndicate_station/mining
name = "\improper northeast of the mining station"
icon_state = "north"
base_turf = /turf/space
/area/syndicate_station/arrivals_dock
name = "\improper docked with station"
@@ -609,6 +609,7 @@ area/space/atmosalert()
/area/skipjack_station/mining
name = "\improper south of mining station"
icon_state = "north"
base_turf = /turf/space
//PRISON
/area/prison
@@ -1304,6 +1305,7 @@ area/space/atmosalert()
requires_power = 1
always_unpowered = 1
dynamic_lighting = 0
base_turf = /turf/space
auxport
name = "\improper Roof Solar Array"
+2 -1
View File
@@ -6,6 +6,7 @@
/area
var/global/global_uid = 0
var/uid
blend_mode = BLEND_MULTIPLY
/area/New()
icon_state = ""
@@ -353,4 +354,4 @@ var/list/mob/living/forced_ambiance_list = new
turfs += F
if (turfs.len)
return pick(turfs)
else return null
else return null
+1 -3
View File
@@ -59,9 +59,7 @@
C.prefs.be_special_role ^= MODE_MERCENARY
obj/item/weapon/antag_spawner/borg_tele/spawn_antag(client/C, turf/T)
var/datum/effect/effect/system/spark_spread/S = new /datum/effect/effect/system/spark_spread
S.set_up(4, 1, src)
S.start()
spark(T, 4, alldirs)
var/mob/living/silicon/robot/H = new /mob/living/silicon/robot/syndicate(T)
H.key = C.key
var/newname = sanitizeSafe(input(H,"Enter a name, or leave blank for the default name.", "Name change","") as text, MAX_NAME_LEN)
@@ -107,7 +107,7 @@ The access requirements on the Asteroid Shuttles' consoles have now been revoked
continue
if (!(C.z in config.admin_levels))
C.update_lumcount(0.15, 0.5, 0)
C.update_lumcount(0.15, 0.15, 0.5)
CHECK_TICK
/datum/universal_state/supermatter_cascade/proc/MiscSet()
+1 -1
View File
@@ -74,7 +74,7 @@
visible_message("A red light flashes on \the [src].")
return
cable.use(amount)
if(deleted(cable))
if(QDELETED(cable))
cable = null
return 1
+29
View File
@@ -134,6 +134,35 @@
else
user << "<span class='warning'>\The [src] has a beaker already.</span>"
return
else if(istype(I, /obj/item/weapon/grab))
var/obj/item/weapon/grab/G = I
var/mob/living/L = G.affecting
if(!istype(L))
user << "<span class='warning'>\The machine won't accept that.</span>"
return
visible_message("[user] starts putting [G.affecting] into the [src].", 3)
if (do_mob(user, G.affecting, 20, needhand = 0))
if(occupant)
user << "<span class='warning'>\The [src] is already occupied.</span>"
return
var/bucklestatus = L.bucklecheck(user)
if (!bucklestatus)//incase the patient got buckled during the delay
return
if(L != G.affecting)//incase it isn't the same mob we started with
return
var/mob/M = G.affecting
M.forceMove(src)
update_use_power(2)
occupant = M
update_icon()
qdel(G)
return
/obj/machinery/sleeper/MouseDrop_T(var/mob/target, var/mob/user)
if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user)|| !ishuman(target))
+2 -2
View File
@@ -100,8 +100,8 @@ obj/machinery/computer/general_air_control/Destroy()
onclose(user, "computer")
/obj/machinery/computer/general_air_control/process()
..()
src.updateUsrDialog()
if (operable())
src.updateUsrDialog()
/obj/machinery/computer/general_air_control/receive_signal(datum/signal/signal)
if(!signal || signal.encryption) return
+1 -3
View File
@@ -878,9 +878,7 @@
cell.update_icon()
cell = null
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
spark(Tsec, 3, alldirs)
new /obj/effect/decal/cleanable/blood/oil(src.loc)
unload(0)
+1 -3
View File
@@ -258,9 +258,7 @@
update_coverage()
//sparks
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, loc)
spark_system.start()
spark(loc, 5)
playsound(loc, "sparks", 50, 1)
/obj/machinery/camera/proc/set_status(var/newstatus)
+1 -5
View File
@@ -174,11 +174,7 @@ var/global/list/engineering_networks = list(
assembly.upgrades.Add(new /obj/item/device/assembly/prox_sensor(assembly))
setPowerUsage()
if(!(src in machines))
if(!machinery_sort_required && ticker)
dd_insertObjectList(machines, src)
else
machines += src
machinery_sort_required = 1
add_machine(src)
update_coverage()
/obj/machinery/camera/proc/setPowerUsage()
+1 -1
View File
@@ -80,5 +80,5 @@
/obj/machinery/computer/operating/process()
if(..())
if(operable())
src.updateDialog()
@@ -42,7 +42,7 @@
crew_announcement.newscast = 1
/obj/machinery/computer/communications/process()
if(..())
if(operable())
if(state != STATE_STATUSDISPLAY)
src.updateDialog()
-5
View File
@@ -23,11 +23,6 @@
power_change()
update_icon()
/obj/machinery/computer/process()
if(stat & (NOPOWER|BROKEN))
return 0
return 1
/obj/machinery/computer/emp_act(severity)
if(prob(20/severity)) set_broken()
..()
+1 -1
View File
@@ -26,7 +26,7 @@
set name = "Eject ID Card"
set src in oview(1)
if(!usr || usr.stat || usr.lying) return
if(!usr || usr.stat || usr.lying || usr.restrained() || !Adjacent(usr)) return
if(scan)
usr << "You remove \the [scan] from \the [src]."
+5 -3
View File
@@ -10,7 +10,7 @@
//Server linked to.
var/obj/machinery/message_server/linkedServer = null
//Sparks effect - For emag
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread
var/datum/effect_system/sparks/spark_system
//Messages - Saves me time if I want to change something.
var/noserver = "<span class='alert'>ALERT: No server detected.</span>"
var/incorrectkey = "<span class='warning'>ALERT: Incorrect decryption key!</span>"
@@ -29,6 +29,9 @@
var/customjob = "Admin"
var/custommessage = "This is a test, please ignore."
/obj/machinery/computer/message_monitor/New()
..()
spark_system = bind_spark(src, 5)
/obj/machinery/computer/message_monitor/attackby(obj/item/weapon/O as obj, mob/living/user as mob)
if(stat & (NOPOWER|BROKEN))
@@ -51,8 +54,7 @@
if(!isnull(src.linkedServer))
emag = 1
screen = 2
spark_system.set_up(5, 0, src)
src.spark_system.start()
src.spark_system.queue()
var/obj/item/weapon/paper/monitorkey/MK = new/obj/item/weapon/paper/monitorkey
MK.loc = src.loc
// Will help make emagging the console not so easy to get away with.
+1 -1
View File
@@ -144,7 +144,7 @@
/obj/machinery/computer/pod/process()
if(!..())
if(inoperable())
return
if(timing)
if(time > 0)
+1 -1
View File
@@ -33,7 +33,7 @@
set name = "Eject ID Card"
set src in oview(1)
if(!usr || usr.stat || usr.lying) return
if(!usr || usr.stat || usr.lying || usr.restrained() || !Adjacent(usr)) return
if(scan)
usr << "You remove \the [scan] from \the [src]."
+1 -1
View File
@@ -42,7 +42,7 @@
set name = "Eject ID Card"
set src in oview(1)
if(!usr || usr.stat || usr.lying) return
if(!usr || usr.stat || usr.lying || usr.restrained() || !Adjacent(usr)) return
if(scan)
usr << "You remove \the [scan] from \the [src]."
@@ -155,3 +155,17 @@
user << desc
if(P && P.loc != src && !istype(P, /obj/item/stack/cable_coil))
user << "<span class='warning'>You cannot add that component to the machine!</span>"
/obj/machinery/constructable_frame/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if (!mover)
return 1
if(istype(mover,/obj/item/projectile) && density)
if (prob(50))
return 1
else
return 0
else if(mover.checkpass(PASSTABLE))
//Animals can run under them, lots of empty space
return 1
return ..()
+7 -12
View File
@@ -177,26 +177,27 @@ for reference:
user << "Barrier lock toggled off."
return
else
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(2, 1, src)
s.start()
spark(src, 2, src)
visible_message("<span class='warning'>BZZzZZzZZzZT</span>")
return
return
else if (istype(W, /obj/item/weapon/wrench))
if (src.health < src.maxhealth)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
src.health = src.maxhealth
src.emagged = 0
src.req_access = list(access_security)
visible_message("<span class='warning'>[user] repairs \the [src]!</span>")
return
else if (src.emagged > 0)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
src.emagged = 0
src.req_access = list(access_security)
visible_message("<span class='warning'>[user] repairs \the [src]!</span>")
return
return
else
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
switch(W.damtype)
if("fire")
src.health -= W.force * 0.75
@@ -241,9 +242,7 @@ for reference:
/* var/obj/item/stack/rods/ =*/
getFromPool(/obj/item/stack/rods, Tsec)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
spark(src, 3, alldirs)
explosion(src.loc,-1,-1,0)
if(src)
@@ -256,16 +255,12 @@ for reference:
src.req_access.Cut()
src.req_one_access.Cut()
user << "You break the ID authentication lock on \the [src]."
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(2, 1, src)
s.start()
spark(src, 2, alldirs)
visible_message("<span class='warning'>BZZzZZzZZzZT</span>")
return 1
else if (src.emagged == 1)
src.emagged = 2
user << "You short out the anchoring mechanism on \the [src]."
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(2, 1, src)
s.start()
spark(src, 2, 1)
visible_message("<span class='warning'>BZZzZZzZZzZT</span>")
return 1
+7 -14
View File
@@ -577,12 +577,12 @@ About the new airlock wires panel:
if(locked && lights && src.arePowerSystemsOn())
icon_state = "door_locked"
if (!has_set_boltlight)
set_light(2, 0.75, COLOR_RED_LIGHT, update_type = UPDATE_NONE)
set_light(2, 0.75, COLOR_RED_LIGHT)
has_set_boltlight = TRUE
else
icon_state = "door_closed"
if (has_set_boltlight)
set_light(0, update_type = UPDATE_NONE)
set_light(0)
has_set_boltlight = FALSE
if(p_open || welded)
overlays = list()
@@ -609,13 +609,9 @@ About the new airlock wires panel:
if((stat & BROKEN) && !(stat & NOPOWER))
overlays += image(icon, "sparks_open")
if (has_set_boltlight)
set_light(0, update_type = UPDATE_NONE)
set_light(0)
has_set_boltlight = FALSE
if (src)
var/turf/T = get_turf(src)
if (T)
T.update_lights_now()
return
/obj/machinery/door/airlock/do_animate(animation)
@@ -733,9 +729,7 @@ About the new airlock wires panel:
if (istype(mover, /obj/item))
var/obj/item/i = mover
if (i.matter && (DEFAULT_WALL_MATERIAL in i.matter) && i.matter[DEFAULT_WALL_MATERIAL] > 0)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
spark(src, 5, alldirs)
return ..()
/obj/machinery/door/airlock/attack_hand(mob/user as mob)
@@ -971,9 +965,8 @@ About the new airlock wires panel:
if ((O.client && !( O.blinded )))
O.show_message("[src.name]'s control panel bursts open, sparks spewing out!")
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
spark(src, 5, alldirs)
update_icon()
return
@@ -1092,7 +1085,7 @@ About the new airlock wires panel:
// playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0)
// next_beep_at = world.time + SecondsToTicks(10)
close_door_at = world.time + 6
close_door_in(6)
return
for(var/turf/turf in locs)
for(var/atom/movable/AM in turf)
+21 -20
View File
@@ -29,8 +29,9 @@
var/hitsound_light = 'sound/effects/Glasshit.ogg'//Sound door makes when hit very gently
var/obj/item/stack/material/steel/repairing
var/block_air_zones = 1 //If set, air zones cannot merge across the door even when it is opened.
var/close_door_at = 0 //When to automatically close the door, if possible
var/open_duration = 150//How long it stays open
var/datum/scheduled_task/close_task
var/datum/scheduled_task/hatch_task
var/hashatch = 0//If 1, this door has hatches, and certain small creatures can move through them without opening the door
var/hatchstate = 0//0: closed, 1: open
@@ -41,8 +42,6 @@
var/hatch_open_sound = 'sound/machines/hatch_open.ogg'
var/hatch_close_sound = 'sound/machines/hatch_close.ogg'
var/hatchclosetime //A world.time value to tell us when the hatch should close
var/image/hatch_image
//Multi-tile doors
@@ -107,7 +106,7 @@
hatchstate = 1
update_icon()
playsound(src.loc, hatch_open_sound, 40, 1, -1)
hatchclosetime = world.time + 29
close_hatch_in(29)
if (istype(mover, /mob/living))
var/mob/living/S = mover
@@ -125,16 +124,18 @@
..()
return
/obj/machinery/door/process()
if(close_door_at && world.time >= close_door_at)
if(autoclose)
close_door_at = next_close_time()
close()
else
close_door_at = 0
if (hatchstate && world.time > hatchclosetime)
/obj/machinery/door/proc/close_door_in(var/time = 5 SECONDS)
spawn(time)
src.close()
/obj/machinery/door/proc/close_hatch_in(var/time = 5 SECONDS)
spawn(time)
close_hatch()
/obj/machinery/door/proc/auto_close()
if (!QDELETED(src) && can_close(FALSE) && autoclose)
close()
/obj/machinery/door/proc/can_open()
if(!density || operating || !ticker)
return 0
@@ -429,9 +430,7 @@
take_damage(damage)
if(3.0)
if(prob(80))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(2, 1, src)
s.start()
spark(src, 2, alldirs)
var/damage = rand(100,150)
if (bolted)
damage *= 0.8
@@ -491,19 +490,23 @@
operating = 0
if(autoclose)
close_door_at = next_close_time()
close_door_in(next_close_time())
return 1
/obj/machinery/door/proc/next_close_time()
return world.time + (normalspeed ? open_duration : 5)
return (normalspeed ? open_duration : 5)
/obj/machinery/door/proc/close(var/forced = 0)
if(!can_close(forced))
if (autoclose)
for (var/atom/movable/AM in get_turf(src))
if (AM.density && AM != src)
spawn(60)
src.auto_close()
return
operating = 1
close_door_at = 0
do_animate("closing")
sleep(3)
src.density = 1
@@ -540,8 +543,6 @@
update_heat_protection(turf)
air_master.mark_for_update(turf)
T.update_lights_now()
return 1
/obj/machinery/door/proc/update_heat_protection(var/turf/simulated/source)
+1 -3
View File
@@ -179,9 +179,7 @@
//Emags and ninja swords? You may pass.
if (istype(I, /obj/item/weapon/melee/energy/blade))
if(emag_act(10, user))
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src.loc)
spark_system.start()
spark(src.loc, 5)
playsound(src.loc, "sparks", 50, 1)
playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1)
visible_message("<span class='warning'>The glass door was sliced open by [user]!</span>")
+2
View File
@@ -11,6 +11,8 @@
var/unlocked = 0
var/open = 0
var/brightness_on = 8 //can't remember what the maxed out value is
light_color = LIGHT_COLOR_TUNGSTEN
light_wedge = LIGHT_WIDE
/obj/machinery/floodlight/New()
src.cell = new(src)
+1 -3
View File
@@ -126,9 +126,7 @@
flick("migniter-spark", src)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(2, 1, src)
s.start()
spark(src, 2, 1)
src.last_spark = world.time
use_power(1000)
var/turf/location = src.loc
+1 -3
View File
@@ -158,9 +158,7 @@ datum/track/New(var/title_name, var/audio)
explosion(src.loc, 0, 0, 1, rand(1,2), 1)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
spark(src, 3, alldirs)
new /obj/effect/decal/cleanable/blood/oil(src.loc)
qdel(src)
@@ -0,0 +1,670 @@
// This folder contains code that was originally ported from Apollo Station and then refactored/optimized/changed.
// Tracks precooked food to stop deep fried baked grilled grilled grilled diona nymph cereal.
/obj/item/weapon/reagent_containers/food/snacks/var/list/cooked = list()
// Root type for cooking machines. See following files for specific implementations.
/obj/machinery/appliance
name = "cooker"
desc = "You shouldn't be seeing this!"
icon = 'icons/obj/cooking_machines.dmi'
var/appliancetype = 0
density = 1
anchored = 1
use_power = 0
idle_power_usage = 5 // Power used when turned on, but not processing anything
active_power_usage = 1000 // Power used when turned on and actively cooking something
var/cooking_power = 1
var/max_contents = 1 // Maximum number of things this appliance can simultaneously cook
var/on_icon // Icon state used when cooking.
var/off_icon // Icon state used when not cooking.
var/cooking // Whether or not the machine is currently operating.
var/cook_type // A string value used to track what kind of food this machine makes.
var/can_cook_mobs // Whether or not this machine accepts grabbed mobs.
var/mobdamagetype = BRUTE // Burn damage for cooking appliances, brute for cereal/candy
var/food_color // Colour of resulting food item.
var/cooked_sound // Sound played when cooking completes.
var/can_burn_food // Can the object burn food that is left inside?
var/burn_chance = 10 // How likely is the food to burn?
var/list/cooking_objs = list() // List of things being cooked
// If the machine has multiple output modes, define them here.
var/selected_option
var/list/output_options = list()
var/list/datum/recipe/available_recipes // List of the recipes this appliance could possibly make
var/container_type = null
var/combine_first = 0//If 1, this appliance will do combinaiton cooking before checking recipes
/obj/machinery/appliance/initialize()
..()
if(output_options.len)
verbs += /obj/machinery/appliance/proc/choose_output
if (!available_recipes)
available_recipes = new
for (var/type in subtypesof(/datum/recipe))
var/datum/recipe/test = new type
if ((appliancetype & test.appliance))
available_recipes += test
else
qdel(test)
/obj/machinery/appliance/Destroy()
for (var/a in cooking_objs)
var/datum/cooking_item/CI = a
qdel(CI.container)//Food is fragile, it probably doesnt survive the destruction of the machine
cooking_objs -= CI
qdel(CI)
return ..()
/obj/machinery/appliance/examine(var/mob/user)
..()
if(Adjacent(usr))
list_contents(user)
return 1
/obj/machinery/appliance/proc/list_contents(var/mob/user)
if (cooking_objs.len)
var/string = "Contains..."
for (var/a in cooking_objs)
var/datum/cooking_item/CI = a
string += "-\a [CI.container.label(null, CI.combine_target)], [report_progress(CI)]</br>"
usr << string
else
usr << span("notice","It is empty.")
/obj/machinery/appliance/proc/report_progress(var/datum/cooking_item/CI)
if (!CI || !CI.max_cookwork)
return null
if (!CI.cookwork)
return "It is cold."
var/progress = CI.cookwork / CI.max_cookwork
if (progress < 0.25)
return "It's barely started cooking."
if (progress < 0.75)
return span("notice","It's cooking away nicely.")
if (progress < 1)
return span("notice", "<b>It's almost ready!</b>")
var/half_overcook = (CI.overcook_mult - 1)*0.5
if (progress < 1+half_overcook)
return span("soghun","<b>It is done !</b>")
if (progress < CI.overcook_mult)
return span("warning","It looks overcooked, get it out!")
else
return span("danger","It is burning!!")
/obj/machinery/appliance/update_icon()
if (!stat && cooking_objs.len)
icon_state = on_icon
else
icon_state = off_icon
/obj/machinery/appliance/verb/toggle_power()
set src in view()
set name = "Toggle Power"
set category = "Object"
if (!isliving(usr))
usr << "Ghosts aren't allowed to toggle power switches"
return
if (usr.stat || usr.restrained() || usr.incapacitated())
return
if (!Adjacent(usr))
if (!issilicon(usr))
usr << "You can't reach the power switch from there, get closer!"
return
if (stat & POWEROFF)//Its turned off
stat &= ~POWEROFF
use_power = 1
if (usr)
usr.visible_message("[usr] turns the [src] on", "You turn on the [src]")
else //Its on, turn it off
stat |= POWEROFF
use_power = 0
if (usr)
usr.visible_message("[usr] turns the [src] off", "You turn off the [src]")
playsound(src, 'sound/machines/click.ogg', 40, 1)
update_icon()
/obj/machinery/appliance/proc/choose_output()
set src in view()
set name = "Choose output"
set category = "Object"
if (!isliving(usr))
usr << "Ghosts aren't allowed to mess with cooking machines!"
return
if (usr.stat || usr.restrained() || usr.incapacitated())
return
if (!Adjacent(usr))
if (!issilicon(usr))
usr << "You can't adjust the [src] from this distance, get closer!"
return
if(output_options.len)
var/choice = input("What specific food do you wish to make with \the [src]?") as null|anything in output_options+"Default"
if(!choice)
return
if(choice == "Default")
selected_option = null
usr << "<span class='notice'>You decide not to make anything specific with \the [src].</span>"
else
selected_option = choice
usr << "<span class='notice'>You prepare \the [src] to make \a [selected_option] with the next thing you put in. Try putting several ingredients in a container!</span>"
//Handles all validity checking and error messages for inserting things
/obj/machinery/appliance/proc/can_insert(var/obj/item/I, var/mob/user)
if(!dropsafety(I))
return 0
// We are trying to cook a grabbed mob.
var/obj/item/weapon/grab/G = I
if(istype(G))
if(!can_cook_mobs)
user << "<span class='warning'>That's not going to fit.</span>"
return 0
if(!isliving(G.affecting))
user << "<span class='warning'>You can't cook that.</span>"
return 0
return 2
if (!has_space(I))
user << "<span class='warning'>There's no room in [src] for that!</span>"
return 0
if (container_type && istype(I, container_type))
return 1
// We're trying to cook something else. Check if it's valid.
var/obj/item/weapon/reagent_containers/food/snacks/check = I
if(istype(check) && islist(check.cooked) && (cook_type in check.cooked))
user << "<span class='warning'>\The [check] has already been [cook_type].</span>"
return 0
else if(istype(check, /obj/item/weapon/reagent_containers/glass))
user << "<span class='warning'>That would probably break [src].</span>"
return 0
else if(istype(check, /obj/item/weapon/disk/nuclear))
user << "Central Command would kill you if you [cook_type] that."
return 0
else if(!istype(check) && !istype(check, /obj/item/weapon/holder))
user << "<span class='warning'>That's not edible.</span>"
return 0
return 1
//This function is overridden by cookers that do stuff with containers
/obj/machinery/appliance/proc/has_space(var/obj/item/I)
if (cooking_objs.len >= max_contents)
return 0
else return 1
/obj/machinery/appliance/attackby(var/obj/item/I, var/mob/user)
if(!cook_type || (stat & (BROKEN)))
user << "<span class='warning'>\The [src] is not working.</span>"
return
var/result = can_insert(I, user)
if (!result)
return
if (result == 2)
var/obj/item/weapon/grab/G = I
if (G && istype(G) && G.affecting)
cook_mob(G.affecting, user)
return
//From here we can start cooking food
add_content(I, user)
update_icon()
//Override for container mechanics
/obj/machinery/appliance/proc/add_content(var/obj/item/I, var/mob/user)
if(!user.unEquip(I))
return
var/datum/cooking_item/CI = has_space(I)
if (istype(I, /obj/item/weapon/reagent_containers/cooking_container) && CI == 1)
var/obj/item/weapon/reagent_containers/cooking_container/CC = I
CI = new /datum/cooking_item/(CC)
I.forceMove(src)
cooking_objs.Add(CI)
user.visible_message("<span class='notice'>\The [user] puts \the [I] into \the [src].</span>")
if (CC.check_contents() == 0)//If we're just putting an empty container in, then dont start any processing.
return
else
if (CI && istype(CI))
I.forceMove(CI.container)
else //Something went wrong
return
if (selected_option)
CI.combine_target = selected_option
// We can actually start cooking now.
user.visible_message("<span class='notice'>\The [user] puts \the [I] into \the [src].</span>")
get_cooking_work(CI)
cooking = 1
return CI
/obj/machinery/appliance/proc/get_cooking_work(var/datum/cooking_item/CI)
for (var/obj/item/J in CI.container)
oilwork(J, CI)
for (var/r in CI.container.reagents.reagent_list)
var/datum/reagent/R = r
if (istype(R, /datum/reagent/nutriment))
CI.max_cookwork += R.volume *2//Added reagents contribute less than those in food items due to granular form
//Nonfat reagents will soak oil
if (!istype(R, /datum/reagent/nutriment/triglyceride))
CI.max_oil += R.volume * 0.25
else
CI.max_cookwork += R.volume
CI.max_oil += R.volume * 0.10
//Rescaling cooking work to avoid insanely long times for large things
var/buffer = CI.max_cookwork
CI.max_cookwork = 0
var/multiplier = 1
var/step = 4
while (buffer > step)
buffer -= step
CI.max_cookwork += step*multiplier
multiplier *= 0.95
CI.max_cookwork += buffer*multiplier
//Just a helper to save code duplication in the above
/obj/machinery/appliance/proc/oilwork(var/obj/item/I, var/datum/cooking_item/CI)
var/obj/item/weapon/reagent_containers/food/snacks/S = I
var/work = 0
if (istype(S))
if (S.reagents)
for (var/r in S.reagents.reagent_list)
var/datum/reagent/R = r
if (istype(R, /datum/reagent/nutriment))
work += R.volume *3//Core nutrients contribute much more than peripheral chemicals
//Nonfat reagents will soak oil
if (!istype(R, /datum/reagent/nutriment/triglyceride))
CI.max_oil += R.volume * 0.35
else
work += R.volume
CI.max_oil += R.volume * 0.15
else if(istype(I, /obj/item/weapon/holder))
var/obj/item/weapon/holder/H = I
if (H.contained)
work += (H.contained.mob_size * H.contained.mob_size * 2)+2
CI.max_cookwork += work
//Called every tick while we're cooking something
/obj/machinery/appliance/proc/do_cooking_tick(var/datum/cooking_item/CI)
if (!CI.max_cookwork)
return 0
var/was_done = 0
if (CI.cookwork >= CI.max_cookwork)
was_done = 1
CI.cookwork += cooking_power
if (!was_done && CI.cookwork >= CI.max_cookwork)
//If cookwork has gone from above to below 0, then this item finished cooking
finish_cooking(CI)
else if (!CI.burned && CI.cookwork > CI.max_cookwork * CI.overcook_mult)
burn_food(CI)
// Gotta hurt.
for(var/obj/item/weapon/holder/H in CI.container.contents)
var/mob/living/M = H.contained
if (M)
M.apply_damage(rand(1,3), mobdamagetype, "chest")
return 1
/obj/machinery/appliance/process()
if (cooking_power > 0 && cooking)
for (var/i in cooking_objs)
do_cooking_tick(i)
/obj/machinery/appliance/proc/finish_cooking(var/datum/cooking_item/CI)
src.visible_message("<span class='notice'>\The [src] pings!</span>")
if(cooked_sound)
playsound(get_turf(src), cooked_sound, 50, 1)
//Check recipes first, a valid recipe overrides other options
var/datum/recipe/recipe = null
var/atom/C = null
if (CI.container)
C = CI.container
else
C = src
recipe = select_recipe(available_recipes,C)
if (recipe)
CI.result_type = 4//Recipe type, a specific recipe will transform the ingredients into a new food
var/list/results = recipe.make_food(C)
var/atom/temp = new /atom //To prevent infinite loops, all results will be moved into a temporary location so they're not considered as inputs for other recipes
for (var/atom/movable/AM in results)
AM.loc = temp
//making multiple copies of a recipe from one container. For example, tons of fries
while (select_recipe(available_recipes,C) == recipe)
var/list/TR = recipe.make_food(C)
for (var/atom/movable/AM in TR) //Move results to buffer
AM.loc = temp
results.Add(TR)
for (var/r in results)
var/obj/item/weapon/reagent_containers/food/snacks/R = r
R.loc = C //Move everything from the buffer back to the container
R.cooked |= cook_type.
qdel(temp) //delete buffer object
temp = null
.=1 //None of the rest of this function is relevant for recipe cooking
else if(CI.combine_target)
CI.result_type = 3//Combination type. We're making something out of our ingredients
.=combination_cook(CI)
else
//Otherwise, we're just doing standard modification cooking. change a color + name
for (var/obj/item/i in CI.container)
modify_cook(i, CI)
//Final step. Cook function just cooks batter for now.
for (var/obj/item/weapon/reagent_containers/food/snacks/S in CI.container)
S.cook()
//Combination cooking involves combining the names and reagents of ingredients into a predefined output object
//The ingredients represent flavours or fillings. EG: donut pizza, cheese bread
/obj/machinery/appliance/proc/combination_cook(var/datum/cooking_item/CI)
var/cook_path = output_options[CI.combine_target]
var/list/words = list()
var/list/cooktypes = list()
var/datum/reagents/buffer = new /datum/reagents(1000)
var/totalcolour
for (var/obj/item/I in CI.container)
var/obj/item/weapon/reagent_containers/food/snacks/S
if (istype(I, /obj/item/weapon/holder))
S = create_mob_food(I, CI)
else if (istype(I, /obj/item/weapon/reagent_containers/food/snacks))
S = I
if (!S)
continue
words |= dd_text2List(S.name," ")
cooktypes |= S.cooked
if (S.reagents && S.reagents.total_volume > 0)
if (S.filling_color)
if (!totalcolour || !buffer.total_volume)
totalcolour = S.filling_color
else
var/t = buffer.total_volume + S.reagents.total_volume
t = buffer.total_volume / y
totalcolour = BlendRGB(totalcolour, S.filling_color, t)
//Blend colours in order to find a good filling color
S.reagents.trans_to_holder(buffer, S.reagents.total_volume)
//Cleanup these empty husk ingredients now
if (I)
qdel(I)
if (S)
qdel(S)
CI.container.reagents.trans_to_holder(buffer, CI.container.reagents.total_volume)
var/obj/item/weapon/reagent_containers/food/snacks/result = new cook_path(CI.container)
buffer.trans_to(result, buffer.total_volume)
//Filling overlay
var/image/I = image(result.icon, "[result.icon_state]_filling")
I.color = totalcolour
result.overlays += I
result.filling_color = totalcolour
//Set the name.
words.Remove(list("and", "the", "in", "is", "bar", "raw", "sticks", "boiled", "fried", "deep", "-o-", "warm", "two", "flavored"))
//Remove common connecting words and unsuitable ones from the list. Unsuitable words include those describing
//the shape, cooked-ness/temperature or other state of an ingredient which doesn't apply to the finished product
words.Remove(result.name)
shuffle(words)
var/num = 6 //Maximum number of words
while (num > 0)
num--
if (!words.len)
break
//Add prefixes from the ingredients in a random order until we run out or hit limit
result.name = "[pop(words)] [result.name]"
//This proc sets the size of the output result
result.update_icon()
return result
//Helper proc for standard modification cooking
/obj/machinery/appliance/proc/modify_cook(var/obj/item/input, var/datum/cooking_item/CI)
var/obj/item/weapon/reagent_containers/food/snacks/result
if (istype(input, /obj/item/weapon/holder))
result = create_mob_food(input, CI)
else if (istype(input, /obj/item/weapon/reagent_containers/food/snacks))
result = input
else
//Nonviable item
return
if (!result)
return
result.cooked |= cook_type.
// Set icon and appearance.
change_product_appearance(result, CI)
// Update strings.
change_product_strings(result, CI)
/obj/machinery/appliance/proc/burn_food(var/datum/cooking_item/CI)
// You dun goofed.
CI.burned = 1
CI.container.clear()
new /obj/item/weapon/reagent_containers/food/snacks/badrecipe(CI.container)
// Produce nasty smoke.
visible_message("<span class='danger'>\The [src] vomits a gout of rancid smoke!</span>")
var/datum/effect/effect/system/smoke_spread/bad/smoke = getFromPool(/datum/effect/effect/system/smoke_spread/bad)
smoke.attach(src)
smoke.set_up(10, 0, get_turf(src), 300)
smoke.start()
/obj/machinery/appliance/attack_hand(var/mob/user)
if (cooking_objs.len)
if (removal_menu(user))
return
else
..()
/obj/machinery/appliance/proc/removal_menu(var/mob/user)
if (can_remove_items(user))
var/list/menuoptions = list()
for (var/a in cooking_objs)
var/datum/cooking_item/CI = a
if (CI.container)
menuoptions[CI.container.label(menuoptions.len)] = CI
var/selection = input(user, "Which item would you like to remove?", "Remove ingredients") as null|anything in menuoptions
if (selection)
var/datum/cooking_item/CI = menuoptions[selection]
eject(CI, user)
update_icon()
return 1
return 0
/obj/machinery/appliance/proc/can_remove_items(var/mob/user)
return 1
/obj/machinery/appliance/proc/eject(var/datum/cooking_item/CI, var/mob/user = null)
var/obj/item/thing
var/delete = 1
var/status = CI.container.check_contents()
if (status == 1)//If theres only one object in a container then we extract that
thing = locate(/obj/item) in CI.container
delete = 0
else//If the container is empty OR contains more than one thing, then we must extract the container
thing = CI.container
if (!user || !user.put_in_hands(thing))
thing.forceMove(get_turf(src))
if (delete)
cooking_objs -= CI
qdel(CI)
else
CI.reset()//reset instead of deleting if the container is left inside
/obj/machinery/appliance/proc/cook_mob(var/mob/living/victim, var/mob/user)
return
/obj/machinery/appliance/proc/change_product_strings(var/obj/item/weapon/reagent_containers/food/snacks/product, var/datum/cooking_item/CI)
product.name = "[cook_type] [product.name]"
product.desc = "[product.desc] It has been [cook_type]."
/obj/machinery/appliance/proc/change_product_appearance(var/obj/item/weapon/reagent_containers/food/snacks/product, var/datum/cooking_item/CI)
if (!product.coating) //Coatings change colour through a new sprite
product.color = food_color
product.filling_color = food_color
//This function creates a food item which represents a dead mob
/obj/machinery/appliance/proc/create_mob_food(var/obj/item/weapon/holder/H, var/datum/cooking_item/CI)
if (!istype(H) || !H.contained)
qdel(H)
return null
var/mob/living/victim = H.contained
if (victim.stat != DEAD)
return null //Victim somehow survived the cooking, they do not become food
victim.calculate_composition()
var/obj/item/weapon/reagent_containers/food/snacks/variable/mob/result = new /obj/item/weapon/reagent_containers/food/snacks/variable/mob(CI.container)
result.w_class = victim.mob_size
result.reagents.add_reagent(victim.composition_reagent, victim.composition_reagent_quantity)
if (victim.reagents)
victim.reagents.trans_to_holder(result.reagents, victim.reagents.total_volume)
if (isanimal(victim))
var/mob/living/simple_animal/SA = victim
result.kitchen_tag = SA.kitchen_tag
result.appearance = victim
var/matrix/M = matrix()
M.Turn(45)
M.Translate(1,-2)
result.transform = M
// all done, now delete the old objects
H.contained = null
qdel(victim)
victim = null
qdel(H)
H = null
return result
/datum/cooking_item
//var/obj/object
var/max_cookwork
var/cookwork
var/overcook_mult = 2
var/result_type = 0
var/obj/item/weapon/reagent_containers/cooking_container/container = null
var/combine_target = null
//Result type is one of the following:
//0 unfinished, no result yet
//1 Standard modification cooking. eg Fried Donk Pocket, Baked wheat, etc
//2 Modification but with a new object that's an inert copy of the old. Generally used for deepfried mice
//3 Combination cooking, EG Donut Bread, Donk pocket pizza, etc
//4:Specific recipe cooking. EG: Turning raw potato sticks into fries
var/burned = 0
var/oil = 0
var/max_oil = 0//Used for fryers.
/datum/cooking_item/New(var/obj/item/I)
container = I
//This is called for containers whose contents are ejected without removing the container
/datum/cooking_item/proc/reset()
//object = null
max_cookwork = 0
cookwork = 0
result_type = 0
burned = 0
max_oil = 0
oil = 0
combine_target = null
//Container is not reset
@@ -1,236 +1,142 @@
// This folder contains code that was originally ported from Apollo Station and then refactored/optimized/changed.
/obj/machinery/appliance/cooker
var/temperature = T20C
var/min_temp = 353//Minimum temperature to do any cooking
var/optimal_temp = 472//Temperature at which we have 100% efficiency. efficiency is lowered on either side of this
var/optimal_power = 0.1//cooking power at 100%
// Tracks precooked food to stop deep fried baked grilled grilled grilled diona nymph cereal.
/obj/item/weapon/reagent_containers/food/snacks/var/list/cooked
var/loss = 1//Temp lost per proc when equalising
var/resistance = 320000//Resistance to heating. combines with active power usage to determine how long heating takes
// Root type for cooking machines. See following files for specific implementations.
/obj/machinery/cooker
name = "cooker"
desc = "You shouldn't be seeing this!"
icon = 'icons/obj/cooking_machines.dmi'
density = 1
anchored = 1
use_power = 1
idle_power_usage = 5
var/light_x = 0
var/light_y = 0
cooking_power = 0
var/on_icon // Icon state used when cooking.
var/off_icon // Icon state used when not cooking.
var/cooking // Whether or not the machine is currently operating.
var/cook_type // A string value used to track what kind of food this machine makes.
var/cook_time = 200 // How many ticks the cooking will take.
var/can_cook_mobs // Whether or not this machine accepts grabbed mobs.
var/food_color // Colour of resulting food item.
var/cooked_sound // Sound played when cooking completes.
var/can_burn_food // Can the object burn food that is left inside?
var/burn_chance = 10 // How likely is the food to burn?
var/obj/item/cooking_obj // Holder for the currently cooking object.
// If the machine has multiple output modes, define them here.
var/selected_option
var/list/output_options = list()
/obj/machinery/cooker/Destroy()
if(cooking_obj)
qdel(cooking_obj)
cooking_obj = null
return ..()
/obj/machinery/cooker/examine()
..()
if(cooking_obj && Adjacent(usr))
usr << "You can see \a [cooking_obj] inside."
/obj/machinery/cooker/attackby(var/obj/item/I, var/mob/user)
if(!cook_type || (stat & (NOPOWER|BROKEN)))
user << "<span class='warning'>\The [src] is not working.</span>"
return
if(cooking)
user << "<span class='warning'>\The [src] is running!</span>"
return
if(!dropsafety(I))
return
// We are trying to cook a grabbed mob.
var/obj/item/weapon/grab/G = I
if(istype(G))
if(!can_cook_mobs)
user << "<span class='warning'>That's not going to fit.</span>"
return
if(!isliving(G.affecting))
user << "<span class='warning'>You can't cook that.</span>"
return
cook_mob(G.affecting, user)
return
// We're trying to cook something else. Check if it's valid.
var/obj/item/weapon/reagent_containers/food/snacks/check = I
if(istype(check) && islist(check.cooked) && (cook_type in check.cooked))
user << "<span class='warning'>\The [check] has already been [cook_type].</span>"
return 0
else if(istype(check, /obj/item/weapon/reagent_containers/glass))
user << "<span class='warning'>That would probably break [src].</span>"
return 0
else if(istype(check, /obj/item/weapon/disk/nuclear))
user << "Central Command would kill you if you [cook_type] that."
return 0
else if(!istype(check) && !istype(check, /obj/item/weapon/holder))
user << "<span class='warning'>That's not edible.</span>"
return 0
// Gotta hurt.
if(istype(cooking_obj, /obj/item/weapon/holder))
for(var/mob/living/M in cooking_obj.contents)
M.apply_damage(rand(30,40), BURN, "chest")
if(!user.unEquip(I))
return
// We can actually start cooking now.
user.visible_message("<span class='notice'>\The [user] puts \the [I] into \the [src].</span>")
cooking_obj = I
cooking_obj.forceMove(src)
cooking = 1
icon_state = on_icon
sleep(cook_time)
// Sanity checks.
if (!check_cooking_obj())
return
if(istype(cooking_obj, /obj/item/weapon/holder))
for(var/mob/living/M in cooking_obj.contents)
M.death()
// Cook the food.
var/cook_path
if(selected_option && output_options.len)
cook_path = output_options[selected_option]
if(!cook_path)
cook_path = /obj/item/weapon/reagent_containers/food/snacks/variable
var/obj/item/weapon/reagent_containers/food/snacks/result = new cook_path(src) //Holy typepaths, Batman.
if(cooking_obj && cooking_obj.reagents && cooking_obj.reagents.total_volume)
cooking_obj.reagents.trans_to(result, cooking_obj.reagents.total_volume)
// Set icon and appearance.
change_product_appearance(result)
// Update strings.
change_product_strings(result)
// Set cooked data.
var/obj/item/weapon/reagent_containers/food/snacks/food_item = cooking_obj
if(istype(food_item) && islist(food_item.cooked))
result.cooked = food_item.cooked.Copy()
else
result.cooked = list()
result.cooked |= cook_type
// Reset relevant variables.
qdel(cooking_obj)
src.visible_message("<span class='notice'>\The [src] pings!</span>")
if(cooked_sound)
playsound(get_turf(src), cooked_sound, 50, 1)
if(!can_burn_food)
icon_state = off_icon
cooking = 0
result.forceMove(get_turf(src))
cooking_obj = null
else
var/failed
var/overcook_period = max(Floor(cook_time/5),1)
cooking_obj = result
while(1)
sleep(overcook_period)
if(!cooking || !result || result.loc != src)
failed = 1
else if(prob(burn_chance))
// You dun goofed.
qdel(cooking_obj)
cooking_obj = new /obj/item/weapon/reagent_containers/food/snacks/badrecipe(src)
// Produce nasty smoke.
visible_message("<span class='danger'>\The [src] vomits a gout of rancid smoke!</span>")
var/datum/effect/effect/system/smoke_spread/bad/smoke = getFromPool(/datum/effect/effect/system/smoke_spread/bad)
smoke.attach(src)
smoke.set_up(10, 0, usr.loc)
smoke.start()
failed = 1
if(failed)
cooking = 0
icon_state = off_icon
break
/obj/machinery/cooker/proc/check_cooking_obj()
if(!cooking_obj || cooking_obj.loc != src)
cooking_obj = null
icon_state = off_icon
cooking = 0
return 0
return 1
/obj/machinery/cooker/attack_hand(var/mob/user)
if(cooking_obj)
user << "<span class='notice'>You grab \the [cooking_obj] from \the [src].</span>"
user.put_in_hands(cooking_obj)
cooking = 0
cooking_obj = null
icon_state = off_icon
return
if(output_options.len)
if(cooking)
user << "<span class='warning'>\The [src] is in use!</span>"
return
var/choice = input("What specific food do you wish to make with \the [src]?") as null|anything in output_options+"Default"
if(!choice)
return
if(choice == "Default")
selected_option = null
user << "<span class='notice'>You decide not to make anything specific with \the [src].</span>"
/obj/machinery/appliance/cooker/examine(var/mob/user)
.=..()
if (.)//no need to duplicate adjacency check
if (!stat)
if (temperature < min_temp)
user << span("warning", "It is heating up.")
else
user << span("notice", "It is running at [round(get_efficiency(), 0.1)]% efficiency!")
user << "Temperature: [round(temperature - T0C, 0.1)]C / [round(optimal_temp - T0C, 0.1)]C"
else
selected_option = choice
user << "<span class='notice'>You prepare \the [src] to make \a [selected_option].</span>"
user << span("warning", "It is switched off.")
/obj/machinery/appliance/cooker/list_contents(var/mob/user)
if (cooking_objs.len)
var/string = "Contains...</br>"
var/num = 0
for (var/a in cooking_objs)
num++
var/datum/cooking_item/CI = a
if (CI && CI.container)
string += "- [CI.container.label(num)], [report_progress(CI)]</br>"
usr << string
else
usr << span("notice","It is empty.")
/obj/machinery/appliance/cooker/proc/get_efficiency()
. = cooking_power / optimal_power
. *= 100
/obj/machinery/appliance/cooker/New()
..()
loss = (active_power_usage / resistance)*0.5
cooking_objs = list()
for (var/i = 0, i < max_contents, i++)
cooking_objs.Add(new /datum/cooking_item/(new container_type(src)))
cooking = 0
/obj/machinery/appliance/cooker/update_icon()
overlays.Cut()
var/image/light
if (use_power == 2 && !stat)
light = image(icon, "light_on")
else
light = image(icon, "light_off")
light.pixel_x = light_x
light.pixel_y = light_y
overlays += light
/obj/machinery/appliance/cooker/process()
if (!stat)
heat_up()
else
var/turf/T = get_turf(src)
if (temperature > T.temperature)
equalize_temperature()
..()
/obj/machinery/cooker/proc/cook_mob(var/mob/living/victim, var/mob/user)
return
/obj/machinery/appliance/cooker/power_change()
.=..()
update_icon()
/obj/machinery/cooker/proc/change_product_strings(var/obj/item/weapon/reagent_containers/food/snacks/product)
if(product.type == /obj/item/weapon/reagent_containers/food/snacks/variable) // Base type, generic.
product.name = "[cook_type] [cooking_obj.name]"
product.desc = "[cooking_obj.desc] It has been [cook_type]."
/obj/machinery/appliance/cooker/proc/update_cooking_power()
var/temp_scale = 0
if(temperature > min_temp)
temp_scale = (temperature - min_temp) / (optimal_temp - min_temp)
//If we're between min and optimal this will yield a value in the range 0-1
if (temp_scale > 1)
//We're above optimal, efficiency goes down as we pass too much over it
if (temp_scale >= 2)
temp_scale = 0
else
temp_scale = 1 - (temp_scale - 1)
cooking_power = optimal_power * temp_scale
/obj/machinery/appliance/cooker/proc/heat_up()
if (temperature < optimal_temp)
if (use_power == 1 && ((optimal_temp - temperature) > 5))
playsound(src, 'sound/machines/click.ogg', 20, 1)
use_power = 2.//If we're heating we use the active power
update_icon()
temperature += active_power_usage / resistance
update_cooking_power()
return 1
else
product.name = "[cooking_obj.name] [product.name]"
if (use_power == 2)
use_power = 1
playsound(src, 'sound/machines/click.ogg', 20, 1)
update_icon()
//We're holding steady. temperature falls more slowly
if (prob(25))
equalize_temperature()
return -1
/obj/machinery/cooker/proc/change_product_appearance(var/obj/item/weapon/reagent_containers/food/snacks/product)
if(product.type == /obj/item/weapon/reagent_containers/food/snacks/variable) // Base type, generic.
product.appearance = cooking_obj
product.color = food_color
product.filling_color = food_color
if(istype(cooking_obj, /obj/item/weapon/holder))
var/matrix/M = matrix()
M.Turn(90)
M.Translate(1,-6)
product.transform = M
/obj/machinery/appliance/cooker/proc/equalize_temperature()
temperature -= loss//Temperature will fall somewhat slowly
update_cooking_power()
//Cookers do differently, they use containers
/obj/machinery/appliance/cooker/has_space(var/obj/item/I)
if (istype(I, /obj/item/weapon/reagent_containers/cooking_container) && cooking_objs.len < max_contents)
//Containers can go into an empty slot
return 1
else
var/image/I = image(product.icon, "[product.icon_state]_filling")
if(istype(cooking_obj, /obj/item/weapon/reagent_containers/food/snacks))
var/obj/item/weapon/reagent_containers/food/snacks/S = cooking_obj
I.color = S.filling_color
if(!I.color)
I.color = food_color
product.overlays += I
//Any food items directly added need an empty container. A slot without a container cant hold food
for (var/datum/cooking_item/CI in cooking_objs)
if (CI.container.check_contents() == 0)
return CI
return 0
/obj/machinery/appliance/cooker/add_content(var/obj/item/I, var/mob/user)
var/datum/cooking_item/CI = ..()
if (CI.combine_target)
user << "The [I] will be used to make a [selected_option]. Output selection is returned to default for future items."
selected_option = null
@@ -5,67 +5,158 @@
desc = "If you can see this description then something is wrong. Please report the bug on the tracker."
bitesize = 2
var/size = 5 //The quantity of reagents which is considered "normal" for this kind of food
//These objects will change size depending on the ratio of reagents to this value
var/min_scale = 0.5
var/max_scale = 2
var/scale = 1
w_class = 2
var/prefix
/obj/item/weapon/reagent_containers/food/snacks/variable/New()
..()
if (reagents)
reagents.maximum_volume = size*8 + 10
else
create_reagents(size*8 + 10)
/obj/item/weapon/reagent_containers/food/snacks/variable/update_icon()
if (reagents && reagents.total_volume)
var/ratio = reagents.total_volume / size
scale = cubert(ratio) //Scaling factor is square root of desired area
scale = Clamp(scale, min_scale, max_scale)
else
scale = min_scale
var/matrix/M = matrix()
M.Scale(scale)
src.transform = M
w_class *= scale
if (!prefix)
if (scale == min_scale)
prefix = "tiny"
else if (scale <= 0.8)
prefix = "small"
else
if (scale >= 1.2)
prefix = "large"
if (scale >= 1.4)
prefix = "extra large"
if (scale >= 1.6)
prefix = "huge"
if (scale >= max_scale)
prefix = "massive"
name = "[prefix] [name]"
/obj/item/weapon/reagent_containers/food/snacks/variable/pizza
name = "personal pizza"
desc = "A personalized pan pizza meant for only one person."
icon_state = "personal_pizza"
size = 20
w_class = 3
/obj/item/weapon/reagent_containers/food/snacks/variable/bread
name = "bread"
desc = "Tasty bread."
icon_state = "breadcustom"
size = 40
w_class = 3
/obj/item/weapon/reagent_containers/food/snacks/variable/pie
name = "pie"
desc = "Tasty pie."
icon_state = "piecustom"
size = 25
/obj/item/weapon/reagent_containers/food/snacks/variable/cake
name = "cake"
desc = "A popular band."
icon_state = "cakecustom"
size = 40
w_class = 3
/obj/item/weapon/reagent_containers/food/snacks/variable/pocket
name = "hot pocket"
desc = "You wanna put a bangin- oh, nevermind."
icon_state = "donk"
size = 8
w_class = 1
/obj/item/weapon/reagent_containers/food/snacks/variable/kebab
name = "kebab"
desc = "Remove this!"
icon_state = "kabob"
size = 10
/obj/item/weapon/reagent_containers/food/snacks/variable/waffles
name = "waffles"
desc = "Made with love."
icon_state = "waffles"
size = 12
/obj/item/weapon/reagent_containers/food/snacks/variable/cookie
name = "cookie"
desc = "Sugar snap!"
icon_state = "cookie"
size = 6
w_class = 1
/obj/item/weapon/reagent_containers/food/snacks/variable/donut
name = "filled donut"
desc = "Donut eat this!" // kill me
icon_state = "donut"
size = 8
w_class = 1
/obj/item/weapon/reagent_containers/food/snacks/variable/jawbreaker
name = "flavored jawbreaker"
desc = "It's like cracking a molar on a rainbow."
icon_state = "jawbreaker"
size = 4
w_class = 1
/obj/item/weapon/reagent_containers/food/snacks/variable/candybar
name = "flavored chocolate bar"
desc = "Made in a factory downtown."
icon_state = "bar"
size = 6
w_class = 1
/obj/item/weapon/reagent_containers/food/snacks/variable/sucker
name = "flavored sucker"
desc = "Suck, suck, suck."
icon_state = "sucker"
size = 4
w_class = 1
/obj/item/weapon/reagent_containers/food/snacks/variable/jelly
name = "jelly"
desc = "All your friends will be jelly."
icon_state = "jellycustom"
size = 8
/obj/item/weapon/reagent_containers/food/snacks/variable/cereal
name = "cereal"
desc = "Crispy and flaky"
icon_state = "cereal_box"
size = 30
w_class = 3
/obj/item/weapon/reagent_containers/food/snacks/variable/cereal/New()
..()
name = pick(list("flakes", "krispies", "crunch", "pops", "O's", "crisp", "loops", "jacks", "clusters"))
/obj/item/weapon/reagent_containers/food/snacks/variable/mob
desc = "Poor little thing"
size = 5
w_class = 1
var/kitchen_tag = "animal"
@@ -0,0 +1,137 @@
/*
The mixer subtype is used for the candymaker and cereal maker. They are similar to cookers but with a few
fundamental differences
1. They have a single container which cant be removed. it will eject multiple contents
2. Items can't be added or removed once the process starts
3. Items are all placed in the same container when added directly
4. They do combining mode only. And will always combine the entire contents of the container into an output
*/
/obj/machinery/appliance/mixer
max_contents = 1
stat = POWEROFF
cooking_power = 0.4
active_power_usage = 3000
idle_power_usage = 50
/obj/machinery/appliance/mixer/examine(var/mob/user)
..()
user << span("notice", "It is currently set to make a [selected_option]")
/obj/machinery/appliance/mixer/New()
..()
cooking_objs.Add(new /datum/cooking_item/(new /obj/item/weapon/reagent_containers/cooking_container(src)))
cooking = 0
selected_option = pick(output_options)
//Mixers cannot-not do combining mode. So the default option is removed from this. A combine target must be chosen
/obj/machinery/appliance/mixer/choose_output()
set src in view()
set name = "Choose output"
set category = "Object"
if(output_options.len)
var/choice = input("What specific food do you wish to make with \the [src]?") as null|anything in output_options
if(!choice)
return
else
selected_option = choice
user << "<span class='notice'>You prepare \the [src] to make \a [selected_option].</span>"
var/datum/cooking_item/CI = cooking_objs[1]
CI.combine_target = selected_option
/obj/machinery/appliance/mixer/has_space(var/obj/item/I)
var/datum/cooking_item/CI = cooking_objs[1]
if (!CI || !CI.container)
return 0
if (CI.container.can_fit(I))
return CI
return 0
/obj/machinery/appliance/mixer/can_remove_items(var/mob/user)
if (stat)
return 1
else
user << span("warning", "You can't remove ingredients while its turned on! Turn it off first or wait for it to finish.")
//Container is not removable
/obj/machinery/appliance/mixer/removal_menu(var/mob/user)
if (can_remove_items(user))
var/list/menuoptions = list()
for (var/a in cooking_objs)
var/datum/cooking_item/CI = a
if (CI.container)
if (!CI.container.check_contents())
user << "There's nothing in the [src] you can remove!"
return
for (var/obj/item/I in CI.container)
menuoptions[I.name] = I
var/selection = input(user, "Which item would you like to remove? If you want to remove chemicals, use an empty beaker.", "Remove ingredients") as null|anything in menuoptions
if (selection)
var/obj/item/I = menuoptions[selection]
if (!user || !user.put_in_hands(I))
I.forceMove(get_turf(src))
update_icon()
return 1
return 0
/obj/machinery/appliance/mixer/toggle_power()
set src in view()
set name = "Toggle Power"
set category = "Object"
var/datum/cooking_item/CI = cooking_objs[1]
if (!CI.container.check_contents())
usr << "There's nothing in it! Add ingredients before turning [src] on!"
return
if (stat & POWEROFF)//Its turned off
stat &= ~POWEROFF
if (usr)
usr.visible_message("[usr] turns the [src] on", "You turn on the [src]")
get_cooking_work(CI)
use_power = 2
else //Its on, turn it off
stat |= POWEROFF
use_power = 0
if (usr)
usr.visible_message("[usr] turns the [src] off", "You turn off the [src]")
playsound(src, 'sound/machines/click.ogg', 40, 1)
update_icon()
/obj/machinery/appliance/mixer/can_insert(var/obj/item/I, var/mob/user)
if (!stat)
user << span("warning","You can't add items while \the [src] is running. Wait for it to finish or turn the power off to abort")
return 0
else
return ..()
/obj/machinery/appliance/mixer/finish_cooking(var/datum/cooking_item/CI)
..()
stat |= POWEROFF
playsound(src, 'sound/machines/click.ogg', 40, 1)
use_power = 0
CI.reset()
update_icon()
/obj/machinery/appliance/mixer/update_icon()
if (!stat)
icon_state = on_icon
else
icon_state = off_icon
/obj/machinery/appliance/mixer/process()
if (!stat)
for (var/i in cooking_objs)
do_cooking_tick(i)
@@ -1,10 +1,12 @@
/obj/machinery/cooker/candy
/obj/machinery/appliance/mixer/candy
name = "candy machine"
desc = "Get yer candied cheese wheels here!"
icon_state = "mixer_off"
off_icon = "mixer_off"
on_icon = "mixer_on"
cook_type = "candied"
appliancetype = CANDYMAKER
cooking_power = 0.6
output_options = list(
"Jawbreaker" = /obj/item/weapon/reagent_containers/food/snacks/variable/jawbreaker,
@@ -13,6 +15,6 @@
"Jelly" = /obj/item/weapon/reagent_containers/food/snacks/variable/jelly
)
/obj/machinery/cooker/candy/change_product_appearance(var/obj/item/weapon/reagent_containers/food/snacks/cooked/product)
/obj/machinery/appliance/mixer/candy/change_product_appearance(var/obj/item/weapon/reagent_containers/food/snacks/cooked/product)
food_color = get_random_colour(1)
. = ..()
@@ -1,4 +1,4 @@
/obj/machinery/cooker/cereal
/obj/machinery/appliance/mixer/cereal
name = "cereal maker"
desc = "Now with Dann O's available!"
icon = 'icons/obj/cooking_machines.dmi'
@@ -6,20 +6,57 @@
cook_type = "cerealized"
on_icon = "cereal_on"
off_icon = "cereal_off"
appliancetype = CEREALMAKER
/obj/machinery/cooker/cereal/change_product_strings(var/obj/item/weapon/reagent_containers/food/snacks/product)
output_options = list(
"Cereal" = /obj/item/weapon/reagent_containers/food/snacks/variable/cereal
)
/*
/obj/machinery/appliance/cereal/change_product_strings(var/obj/item/weapon/reagent_containers/food/snacks/product, var/datum/cooking_item/CI)
. = ..()
product.name = "box of [cooking_obj.name] cereal"
product.name = "box of [CI.object.name] cereal"
/obj/machinery/cooker/cereal/change_product_appearance(var/obj/item/weapon/reagent_containers/food/snacks/product)
/obj/machinery/appliance/cereal/change_product_appearance(var/obj/item/weapon/reagent_containers/food/snacks/product, var/datum/cooking_item/CI)
product.icon = 'icons/obj/food.dmi'
product.icon_state = "cereal_box"
product.filling_color = cooking_obj.color
product.filling_color = CI.object.color
var/image/food_image = image(cooking_obj.icon, cooking_obj.icon_state)
food_image.color = cooking_obj.color
food_image.overlays += cooking_obj.overlays
var/image/food_image = image(CI.object.icon, CI.object.icon_state)
food_image.color = CI.object.color
food_image.overlays += CI.object.overlays
food_image.transform *= 0.7
product.overlays += food_image
*/
/obj/machinery/appliance/mixer/cereal/combination_cook(var/datum/cooking_item/CI)
var/list/images = list()
var/num = 0
for (var/obj/item/I in CI.container).
if (istype(I, /obj/item/weapon/reagent_containers/food/snacks/variable/cereal))
//Images of cereal boxes on cereal boxes is dumb
continue
var/image/food_image = image(I.icon, I.icon_state)
food_image.color = I.color
food_image.overlays += I.overlays
food_image.transform *= 0.7 - (num * 0.05)
food_image.pixel_x = rand(-2,2)
food_image.pixel_y = rand(-3,5)
if (!images[I.icon_state])
images[I.icon_state] = food_image
num++
if (num > 3)
continue
var/obj/item/weapon/reagent_containers/food/snacks/result = ..()
result.color = result.filling_color
for (var/i in images)
result.overlays += images[i]
@@ -0,0 +1,131 @@
//Cooking containers are used in ovens and fryers, to hold multiple ingredients for a recipe.
//They work fairly similar to the microwave - acting as a container for objects and reagents,
//which can be checked against recipe requirements in order to cook recipes that require several things
/obj/item/weapon/reagent_containers/cooking_container
icon = 'icons/obj/cooking_machines.dmi'
var/shortname
var/max_space = 20//Maximum sum of w-classes of foods in this container at once
var/max_reagents = 80//Maximum units of reagents
/obj/item/weapon/reagent_containers/cooking_container/New()
..()
create_reagents(max_reagents)
flags |= OPENCONTAINER
/obj/item/weapon/reagent_containers/cooking_container/examine(var/mob/user)
..()
if (contents.len)
var/string = "It contains....</br>"
for (var/atom/movable/A in contents)
string += "[A.name] </br>"
user << span("notice", string)
if (reagents.total_volume)
user << span("notice", "It contains [reagents.total_volume]u of reagents.")
/obj/item/weapon/reagent_containers/cooking_container/attackby(var/obj/item/I as obj, var/mob/user as mob)
if (istype(I, /obj/item/weapon/reagent_containers/food/snacks))
if (!can_fit(I))
user << span("warning","There's no more space in the [src] for that!")
return 0
if(!user.unEquip(I))
return
I.forceMove(src)
user << span("notice", "You put the [I] into the [src]")
/obj/item/weapon/reagent_containers/cooking_container/verb/empty()
set src in view()
set name = "Empty Container"
set category = "Object"
set desc = "Removes items from the container. does not remove reagents."
if (!Adjacent(usr))
usr << "You can't reach the [src] from there, get closer!"
return
for (var/atom/movable/A in contents)
A.forceMove(get_turf(src))
/obj/item/weapon/reagent_containers/cooking_container/proc/check_contents()
if (contents.len == 0)
if (!reagents || reagents.total_volume == 0)
return 0//Completely empty
else if (contents.len == 1)
if (!reagents || reagents.total_volume == 0)
return 1//Contains only a single object which can be extracted alone
return 2//Contains multiple objects and/or reagents
//Deletes contents of container.
//Used when food is burned, before replacing it with a burned mess
/obj/item/weapon/reagent_containers/cooking_container/proc/clear()
for (var/atom/a in contents)
qdel(a)
if (reagents)
reagents.clear_reagents()
/obj/item/weapon/reagent_containers/cooking_container/proc/label(var/number, var/CT = null)
//This returns something like "Fryer basket 1 - empty"
//The latter part is a brief reminder of contents
//This is used in the removal menu
. = shortname
if (!isnull(number))
.+= " [number]"
.+= " - "
if (CT)
.+=CT
else if (contents.len)
for (var/obj/O in contents)
.+=O.name//Just append the name of the first object
return
else if (reagents && reagents.total_volume > 0)
var/datum/reagent/R = reagents.get_master_reagent()
.+=R.name//Append name of most voluminous reagent
return
else
. += "empty"
/obj/item/weapon/reagent_containers/cooking_container/proc/can_fit(var/obj/item/I)
var/total = 0
for (var/obj/item/J in contents)
total += J.w_class
if((max_space - total) >= I.w_class)
return 1
//Takes a reagent holder as input and distributes its contents among the items in the container
//Distribution is weighted based on the volume already present in each item
/obj/item/weapon/reagent_containers/cooking_container/proc/soak_reagent(var/datum/reagents/holder)
var/total = 0
var/list/weights = list()
for (var/obj/item/I in contents)
if (I.reagents && I.reagents.total_volume)
total += I.reagents.total_volume
weights[I] = I.reagents.total_volume
if (total > 0)
for (var/obj/item/I in contents)
if (weights[I])
holder.trans_to(I, weights[I] / total)
/obj/item/weapon/reagent_containers/cooking_container/oven
name = "Oven Dish"
shortname = "shelf"
desc = "Put ingredients in this for cooking to a recipe,in an oven."
icon_state = "ovendish"
max_space = 30
max_reagents = 120
/obj/item/weapon/reagent_containers/cooking_container/fryer
name = "Fryer basket"
shortname = "basket"
desc = "Belongs in a deep fryer, put ingredients in it for cooking to a recipe"
icon_state = "basket"
@@ -1,4 +1,4 @@
/obj/machinery/cooker/fryer
/obj/machinery/appliance/cooker/fryer
name = "deep fryer"
desc = "Deep fried <i>everything</i>."
icon_state = "fryer_off"
@@ -8,27 +8,164 @@
off_icon = "fryer_off"
food_color = "#FFAD33"
cooked_sound = 'sound/machines/ding.ogg'
appliancetype = FRYER
active_power_usage = 24000
//24 KW, based on real world values for a large commercial fryer.
/obj/machinery/cooker/fryer/cook_mob(var/mob/living/victim, var/mob/user)
optimal_power = 0.35
idle_power_usage = 6000
//Power used to maintain temperature once it's heated.
//Going with 25% of the active power. This is a somewhat arbitrary value
resistance = 90000
//By default, about 15 mins to heat up.
max_contents = 2
container_type = /obj/item/weapon/reagent_containers/cooking_container/fryer
stat = POWEROFF//Starts turned off
var/datum/reagents/oil
var/optimal_oil = 9000//90 litres of cooking oil
/obj/machinery/appliance/cooker/fryer/examine(var/mob/user)
if (..())//no need to duplicate adjacency check
user << "Oil Level: [oil.total_volume]/[optimal_oil]"
/obj/machinery/appliance/cooker/fryer/New()
..()
oil = new/datum/reagents(optimal_oil * 1.25, src)
var/variance = rand()*0.15
//Fryer is always a little below full, but its usually negligible
if (prob(20))
//Sometimes the fryer will start with much less than full oil, significantly impacting efficiency until filled
variance = rand()*0.5
oil.add_reagent("cornoil", optimal_oil*(1 - variance))
/obj/machinery/appliance/cooker/fryer/heat_up()
if (..())
//Set temperature of oil reagent
var/datum/reagent/nutriment/triglyceride/oil/OL = oil.get_master_reagent()
if (OL && istype(OL))
OL.data["temperature"] = temperature
/obj/machinery/appliance/cooker/fryer/equalize_temperature()
if (..())
//Set temperature of oil reagent
var/datum/reagent/nutriment/triglyceride/oil/OL = oil.get_master_reagent()
if (OL && istype(OL))
OL.data["temperature"] = temperature
/obj/machinery/appliance/cooker/fryer/update_cooking_power()
..()//In addition to parent temperature calculation
//Fryer efficiency also drops when oil levels arent optimal
var/oil_level = 0
var/datum/reagent/nutriment/triglyceride/oil/OL = oil.get_master_reagent()
if (OL && istype(OL))
oil_level = OL.volume
var/oil_efficiency = 0
if (oil_level)
oil_efficiency = oil_level / optimal_oil
if (oil_efficiency > 1)
//We're above optimal, efficiency goes down as we pass too much over it
oil_efficiency = 1 - (oil_efficiency - 1)
cooking_power *= oil_efficiency
/obj/machinery/appliance/cooker/fryer/update_icon()
if (cooking)
icon_state = on_icon
else
icon_state = off_icon
..()
//Fryer gradually infuses any cooked food with oil. Moar calories
//This causes a slow drop in oil levels, encouraging refill after extended use
/obj/machinery/appliance/cooker/fryer/do_cooking_tick(var/datum/cooking_item/CI)
if(..() && (CI.oil < CI.max_oil) && prob(20))
var/datum/reagents/buffer = new /datum/reagents(2)
oil.trans_to_holder(buffer, min(0.5, CI.max_oil - CI.oil))
CI.oil += buffer.total_volume
CI.container.soak_reagent(buffer)
//To solve any odd logic problems with results having oil as part of their compiletime ingredients.
//Upon finishing a recipe the fryer will analyse any oils in the result, and replace them with our oil
//As well as capping the total to the max oil
/obj/machinery/appliance/cooker/fryer/finish_cooking(var/datum/cooking_item/CI)
..()
var/total_oil = 0
var/total_our_oil = 0
var/total_removed = 0
var/datum/reagent/our_oil = oil.get_master_reagent()
for (var/obj/item/I in CI.container)
if (I.reagents && I.reagents.total_volume)
for (var/datum/reagent/R in I.reagents.reagent_list)
if (istype(R, /datum/reagent/nutriment/triglyceride/oil))
total_oil += R.volume
if (R.id != our_oil.id)
total_removed += R.volume
I.reagents.remove_reagent(R.id, R.volume)
else
total_our_oil += R.volume
if (total_removed > 0 || total_oil != CI.max_oil)
total_oil = min(total_oil, CI.max_oil)
if (total_our_oil < total_oil)
//If we have less than the combined total, then top up from our reservoir
var/datum/reagents/buffer = new /datum/reagents(INFINITY)
oil.trans_to_holder(buffer, total_oil - total_our_oil)
CI.container.soak_reagent(buffer)
else if (total_our_oil > total_oil)
//If we have more than the maximum allowed then we delete some.
//This could only happen if one of the objects spawns with the same type of oil as ours
var/portion = 1 - (total_oil / total_our_oil) //find the percentage to remove
for (var/obj/item/I in CI.container)
if (I.reagents && I.reagents.total_volume)
for (var/datum/reagent/R in I.reagents.reagent_list)
if (R.id == our_oil.id)
I.reagents.remove_reagent(R.id, R.volume*portion)
/obj/machinery/appliance/cooker/fryer/cook_mob(var/mob/living/victim, var/mob/user)
if(!istype(victim))
return
user.visible_message("<span class='danger'>\The [user] starts pushing \the [victim] into \the [src]!</span>")
icon_state = on_icon
cooking = 1
//user.visible_message("<span class='danger'>\The [user] starts pushing \the [victim] into \the [src]!</span>")
if(!do_mob(user, victim, 20))
cooking = 0
icon_state = off_icon
return
//Removed delay on this action in favour of a cooldown after it
//If you can lure someone close to the fryer and grab them then you deserve success.
//And a delay on this kind of niche action just ensures it never happens
//Cooldown ensures it can't be spammed to instakill someone
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN*3)
if(!victim || !victim.Adjacent(user))
user << "<span class='danger'>Your victim slipped free!</span>"
cooking = 0
icon_state = off_icon
return
var/damage = rand(7,13)
//Though this damage seems reduced, some hot oil is transferred to the victim and will burn them for a while after
var/datum/reagent/nutriment/triglyceride/oil/OL = oil.get_master_reagent()
damage *= OL.heatdamage(victim)
var/obj/item/organ/external/E
var/nopain
if(ishuman(victim) && user.zone_sel.selecting != "groin" && user.zone_sel.selecting != "chest")
@@ -40,28 +177,62 @@
nopain = 1
user.visible_message("<span class='danger'>\The [user] shoves \the [victim][E ? "'s [E.name]" : ""] into \the [src]!</span>")
if (damage > 0)
if(E)
if(E)
E.take_damage(0, rand(20,30))
if(E.children && E.children.len)
for(var/obj/item/organ/external/child in E.children)
if(nopain && nopain < 2 && !(child.robotic >= ORGAN_ROBOT))
nopain = 0
child.take_damage(0, rand(20,30))
else
victim.apply_damage(rand(30,40), BURN, user.zone_sel.selecting)
if(E.children && E.children.len)
for(var/obj/item/organ/external/child in E.children)
if(nopain && nopain < 2 && !(child.robotic >= ORGAN_ROBOT))
nopain = 0
child.take_damage(0, damage)
damage -= (damage*0.5)//IF someone's arm is plunged in, the hand should take most of it
E.take_damage(0, damage)
else
victim.apply_damage(damage, BURN, user.zone_sel.selecting)
if(!nopain)
victim << "<span class='danger'>Agony consumes you as searing hot oil scorches your [E ? E.name : "flesh"] horribly!</span>"
victim.emote("scream")
else
victim << "<span class='danger'>Searing hot oil scorches your [E ? E.name : "flesh"]!</span>"
if(!nopain)
victim << "<span class='danger'>Agony consumes you as searing hot oil scorches your [E ? E.name : "flesh"] horribly!</span>"
victim.emote("scream")
else
victim << "<span class='danger'>Searing hot oil scorches your [E ? E.name : "flesh"]!</span>"
if(victim.client)
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Has [cook_type] \the [victim] ([victim.ckey]) in \a [src]</font>")
victim.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been [cook_type] in \a [src] by [user.name] ([user.ckey])</font>")
msg_admin_attack("[user] ([user.ckey]) [cook_type] \the [victim] ([victim.ckey]) in \a [src]. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)")
icon_state = off_icon
cooking = 0
//Coat the victim in some oil
oil.trans_to(victim, 40)
return
/obj/machinery/appliance/cooker/fryer/attackby(var/obj/item/I, var/mob/user)
if(istype(I, /obj/item/weapon/reagent_containers/glass) && I.reagents)
if (I.reagents.total_volume <= 0 && oil)
//Its empty, handle scooping some hot oil out of the fryer
oil.trans_to(I, I.reagents.maximum_volume)
user.visible_message("[user] scoops some oil out of \the [src]", span("notice","You scoop some oil out of \the [src]"))
return 1
else
//It contains stuff, handle pouring any oil into the fryer
//Possibly in future allow pouring non-oil reagents in, in order to sabotage it and poison food.
//That would really require coding some sort of filter or better replacement mechanism first
//So for now, restrict to oil only
var/amount = 0
for (var/datum/reagent/R in I.reagents.reagent_list)
if (istype(R, /datum/reagent/nutriment/triglyceride/oil))
var/delta = oil.get_free_space()
delta = min(delta, R.volume)
oil.add_reagent(R.id, delta)
I.reagents.remove_reagent(R.id, delta)
amount += delta
if (amount > 0)
user.visible_message("[user] pours some oil into \the [src]", span("notice","You pour [amount]u of oil into \the [src]"))
return 1
//If neither of the above returned, then call parent as normal
..()
@@ -1,9 +1,8 @@
/obj/machinery/cooker/grill
/obj/machinery/appliance/cooker/grill
name = "grill"
desc = "Backyard grilling, IN SPACE."
icon_state = "grill_off"
cook_type = "grilled"
cook_time = 100
food_color = "#A34719"
on_icon = "grill_on"
off_icon = "grill_off"
@@ -1,4 +1,4 @@
/obj/machinery/cooker/oven
/obj/machinery/appliance/cooker/oven
name = "oven"
desc = "Cookies are ready, dear."
icon = 'icons/obj/cooking_machines.dmi'
@@ -6,18 +6,107 @@
on_icon = "oven_on"
off_icon = "oven_off"
cook_type = "baked"
cook_time = 300
appliancetype = OVEN
food_color = "#A34719"
can_burn_food = 1
active_power_usage = 19000
//Based on a double deck electric convection oven
resistance = 72000
idle_power_usage = 6000
//uses 30% power to stay warm
optimal_power = 0.2
light_x = 2
max_contents = 5
container_type = /obj/item/weapon/reagent_containers/cooking_container/oven
stat = POWEROFF//Starts turned off
var/open = 1
output_options = list(
"Personal Pizza" = /obj/item/weapon/reagent_containers/food/snacks/variable/pizza,
"Pizza" = /obj/item/weapon/reagent_containers/food/snacks/variable/pizza,
"Bread" = /obj/item/weapon/reagent_containers/food/snacks/variable/bread,
"Pie" = /obj/item/weapon/reagent_containers/food/snacks/variable/pie,
"Small Cake" = /obj/item/weapon/reagent_containers/food/snacks/variable/cake,
"Cake" = /obj/item/weapon/reagent_containers/food/snacks/variable/cake,
"Hot Pocket" = /obj/item/weapon/reagent_containers/food/snacks/variable/pocket,
"Kebab" = /obj/item/weapon/reagent_containers/food/snacks/variable/kebab,
"Waffles" = /obj/item/weapon/reagent_containers/food/snacks/variable/waffles,
"Cookie" = /obj/item/weapon/reagent_containers/food/snacks/variable/cookie,
"Donut" = /obj/item/weapon/reagent_containers/food/snacks/variable/donut
)
/obj/machinery/appliance/cooker/oven/update_icon()
if (!open)
if (!stat)
icon_state = "ovenclosed_on"
else
icon_state = "ovenclosed_off"
else
icon_state = "ovenopen"
..()
/obj/machinery/appliance/cooker/oven/AltClick(var/mob/user)
if(user.stat || user.restrained()) return
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)//No spamming the door, it makes a sound
toggle_door()
/obj/machinery/appliance/cooker/oven/verb/toggle_door()
set src in view()
set name = "Open/close oven door"
set category = "Object"
if (!Adjacent(usr))
usr << "You can't reach the [src] from there, get closer!"
return
if (open)
open = 0
loss = (active_power_usage / resistance)*0.5
else
open = 1
loss = (active_power_usage / resistance)*10
//When the oven door is opened, heat is lost MUCH faster
playsound(src, 'sound/machines/hatch_open.ogg', 20, 1)
update_icon()
/obj/machinery/appliance/cooker/oven/can_insert(var/obj/item/I, var/mob/user)
if (!open)
user << "<span class='warning'>You can't put anything in while the door is closed!</span>"
return 0
else
return ..()
//If an oven's door is open it will lose heat every proc, even if it also gained it
//But dont call equalize twice in one stack. A return value of -1 from the parent indicates equalize was already called
/obj/machinery/appliance/cooker/oven/heat_up()
.=..()
if (open && . != -1)
var/turf/T = get_turf(src)
if (temperature > T.temperature)
equalize_temperature()
/obj/machinery/appliance/cooker/oven/can_remove_items(var/mob/user)
if (!open)
user << "<span class='warning'>You can't take anything out while the door is closed!</span>"
return 0
else
return ..()
//Oven has lots of recipes and combine options. The chance for interference is high, so
//If a combine target is set the oven will do it instead of checking recipes
/obj/machinery/appliance/cooker/oven/finish_cooking(var/datum/cooking_item/CI)
if(CI.combine_target)
CI.result_type = 3//Combination type. We're making something out of our ingredients
combination_cook(CI)
return
else
..()
+55 -24
View File
@@ -8,7 +8,7 @@
anchored = 1
use_power = 1
idle_power_usage = 5
active_power_usage = 100
active_power_usage = 2000
flags = OPENCONTAINER | NOREACT
var/operating = 0 // Is it on?
var/dirty = 0 // = {0..100} Does it need cleaning?
@@ -17,7 +17,7 @@
var/global/list/acceptable_items // List of the items you can put in
var/global/list/acceptable_reagents // List of the reagents you can put in
var/global/max_n_of_items = 0
var/appliancetype = MICROWAVE
// see code/modules/food/recipes_microwave.dm for recipes
@@ -32,7 +32,11 @@
if (!available_recipes)
available_recipes = new
for (var/type in (typesof(/datum/recipe)-/datum/recipe))
available_recipes+= new type
var/datum/recipe/test = new type
if ((test.appliance & appliancetype))
available_recipes += test
else
qdel(test)
acceptable_items = new
acceptable_reagents = new
for (var/datum/recipe/recipe in available_recipes)
@@ -137,13 +141,13 @@
return 1
else if(istype(O,/obj/item/weapon/crowbar))
user.visible_message( \
"<span class='notice'>\The [user] begins [src.anchored ? "securing" : "unsecuring"] the microwave.</span>", \
"<span class='notice'>You attempt to [src.anchored ? "secure" : "unsecure"] the microwave.</span>"
"<span class='notice'>\The [user] begins [src.anchored ? "unsecuring" : "securing"] the microwave.</span>", \
"<span class='notice'>You attempt to [src.anchored ? "unsecure" : "secure"] the microwave.</span>"
)
if (do_after(user,20))
user.visible_message( \
"<span class='notice'>\The [user] [src.anchored ? "secures" : "unsecures"] the microwave.</span>", \
"<span class='notice'>You [src.anchored ? "secure" : "unsecure"] the microwave.</span>"
"<span class='notice'>\The [user] [src.anchored ? "unsecures" : "secures"] the microwave.</span>", \
"<span class='notice'>You [src.anchored ? "unsecure" : "secure"] the microwave.</span>"
)
src.anchored = !src.anchored
else
@@ -239,7 +243,7 @@
return
start()
if (reagents.total_volume==0 && !(locate(/obj) in contents)) //dry run
if (!wzhzhzh(10))
if (!wzhzhzh(16))
abort()
return
stop()
@@ -250,17 +254,17 @@
if (!recipe)
dirty += 1
if (prob(max(10,dirty*5)))
if (!wzhzhzh(4))
if (!wzhzhzh(16))
abort()
return
muck_start()
wzhzhzh(4)
wzhzhzh(16)
muck_finish()
cooked = fail()
cooked.loc = src.loc
return
else if (has_extra_item())
if (!wzhzhzh(4))
if (!wzhzhzh(16))
abort()
return
broke()
@@ -268,7 +272,7 @@
cooked.loc = src.loc
return
else
if (!wzhzhzh(10))
if (!wzhzhzh(40))
abort()
return
stop()
@@ -276,7 +280,7 @@
cooked.loc = src.loc
return
else
var/halftime = round(recipe.time/10/2)
var/halftime = round((recipe.time*4)/10/2)
if (!wzhzhzh(halftime))
abort()
return
@@ -285,17 +289,36 @@
cooked = fail()
cooked.loc = src.loc
return
cooked = recipe.make_food(src)
//Making multiple copies of a recipe
var/result = recipe.result
var/valid = 1
var/list/cooked_items = list()
while(valid)
cooked_items += recipe.make_food(src)
valid = 0
recipe = select_recipe(available_recipes,src)
if (recipe && recipe.result == result)
valid = 1
//Any leftover reagents are divided amongst the foods
var/total = reagents.total_volume
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)
S.cook()
dispose(0) //clear out anything left
stop()
if(cooked)
cooked.loc = src.loc
return
/obj/machinery/microwave/proc/wzhzhzh(var/seconds as num) // Whoever named this proc is fucking literally Satan. ~ Z
for (var/i=1 to seconds)
if (stat & (NOPOWER|BROKEN))
return 0
use_power(500)
use_power(active_power_usage)
sleep(10)
return 1
@@ -325,13 +348,14 @@
src.icon_state = "mw"
src.updateUsrDialog()
/obj/machinery/microwave/proc/dispose()
for (var/obj/O in contents)
O.loc = src.loc
/obj/machinery/microwave/proc/dispose(var/message = 1)
for (var/atom/movable/A in contents)
A.forceMove(loc)
if (src.reagents.total_volume)
src.dirty++
src.reagents.clear_reagents()
usr << "<span class='notice'>You dispose of the microwave contents.</span>"
if (message)
usr << "<span class='notice'>You dispose of the microwave contents.</span>"
src.updateUsrDialog()
/obj/machinery/microwave/proc/muck_start()
@@ -348,9 +372,7 @@
src.updateUsrDialog()
/obj/machinery/microwave/proc/broke()
var/datum/effect/effect/system/spark_spread/s = new
s.set_up(2, 1, src)
s.start()
spark(src, 2, alldirs)
src.icon_state = "mwb" // Make it look all busted up and shit
src.visible_message("<span class='warning'>The microwave breaks!</span>") //Let them know they're stupid
src.broken = 2 // Make it broken so it can't be used util fixed
@@ -389,3 +411,12 @@
if ("dispose")
dispose()
return
/obj/machinery/microwave/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if (!mover)
return 1
if(mover.checkpass(PASSTABLE))
//Animals can run under them, lots of empty space
return 1
return ..()
+10 -10
View File
@@ -118,14 +118,11 @@ Class Procs:
..(l)
if(d)
set_dir(d)
if(!machinery_sort_required && ticker)
dd_insertObjectList(machines, src)
else
machines += src
machinery_sort_required = 1
add_machine(src)
/obj/machinery/Destroy()
machines -= src
remove_machine(src)
if(component_parts)
for(var/atom/A in component_parts)
if(A.loc == src) // If the components are inside the machine, delete them.
@@ -141,7 +138,12 @@ Class Procs:
if(!(use_power || idle_power_usage || active_power_usage))
return PROCESS_KILL
return
return M_NO_PROCESS
/obj/machinery/proc/get_process_type()
. |= M_PROCESSES
if (use_power || idle_power_usage || active_power_usage)
. |= M_USES_POWER
/obj/machinery/emp_act(severity)
if(use_power && stat == 0)
@@ -280,9 +282,7 @@ Class Procs:
return 0
if(!prob(prb))
return 0
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
spark(src, 5, alldirs)
if (electrocute_mob(user, get_area(src), src, 0.7))
var/area/temp_area = get_area(src)
if(temp_area)
+5
View File
@@ -11,6 +11,7 @@ var/bomb_set
var/lighthack = 0
var/timeleft = 120
var/timing = 0
var/alerted = 0
var/r_code = "ADMIN"
var/code = ""
var/yes_code = 0
@@ -290,6 +291,10 @@ var/bomb_set
update_icon()
else
secure_device()
if(alerted == 0)
set_security_level(SEC_LEVEL_DELTA)
alerted = 1
if (href_list["safety"])
if (wires.IsIndexCut(NUCLEARBOMB_WIRE_SAFETY))
usr << "<span class='warning'>Nothing happens, something might be wrong with the wiring.</span>"
+9 -9
View File
@@ -463,7 +463,7 @@ Buildable meters
var/turf/T = P.loc
P.level = !T.is_plating() ? 2 : 1
P.initialize()
if (deleted(P))
if (QDELETED(P))
usr << pipefailtext
return 1
P.build_network()
@@ -482,7 +482,7 @@ Buildable meters
var/turf/T = P.loc
P.level = !T.is_plating() ? 2 : 1
P.initialize()
if (deleted(P))
if (QDELETED(P))
usr << pipefailtext
return 1
P.build_network()
@@ -501,7 +501,7 @@ Buildable meters
var/turf/T = P.loc
P.level = !T.is_plating() ? 2 : 1
P.initialize()
if (deleted(P))
if (QDELETED(P))
usr << pipefailtext
return 1
P.build_network()
@@ -520,7 +520,7 @@ Buildable meters
var/turf/T = P.loc
P.level = !T.is_plating() ? 2 : 1
P.initialize()
if (deleted(P))
if (QDELETED(P))
usr << pipefailtext
return 1
P.build_network()
@@ -537,7 +537,7 @@ Buildable meters
P.initialize_directions = pipe_dir //this var it's used to know if the pipe is bent or not
P.initialize_directions_he = pipe_dir
P.initialize()
if (deleted(P))
if (QDELETED(P))
usr << pipefailtext
return 1
P.build_network()
@@ -572,7 +572,7 @@ Buildable meters
var/turf/T = M.loc
M.level = !T.is_plating() ? 2 : 1
M.initialize()
if (deleted(M))
if (QDELETED(M))
usr << pipefailtext
return 1
M.build_network()
@@ -641,7 +641,7 @@ Buildable meters
var/turf/T = M.loc
M.level = !T.is_plating() ? 2 : 1
M.initialize()
if (deleted(M))
if (QDELETED(M))
usr << pipefailtext
return 1
M.build_network()
@@ -718,7 +718,7 @@ Buildable meters
P.initialize_directions = src.get_pdir()
P.initialize_directions_he = src.get_hdir()
P.initialize()
if (deleted(P))
if (QDELETED(P))
usr << pipefailtext //"There's nothing to connect this pipe to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)"
return 1
P.build_network()
@@ -901,7 +901,7 @@ Buildable meters
var/turf/T = P.loc
P.level = !T.is_plating() ? 2 : 1
P.initialize()
if (deleted(P))
if (QDELETED(P))
usr << pipefailtext
return 1
P.build_network()
+4 -6
View File
@@ -55,7 +55,7 @@
var/shot_sound //what sound should play when the turret fires
var/eshot_sound //what sound should play when the emagged turret fires
var/datum/effect/effect/system/spark_spread/spark_system //the spark system, used for generating... sparks?
var/datum/effect_system/sparks/spark_system //the spark system, used for generating... sparks?
var/wrenching = 0
var/last_target //last target fired at, prevents turrets from erratically firing at all valid targets in range
@@ -81,9 +81,7 @@
req_one_access = list(access_security, access_heads)
//Sets up a spark system
spark_system = new /datum/effect/effect/system/spark_spread
spark_system.set_up(5, 0, src)
spark_system.attach(src)
spark_system = bind_spark(src, 5)
setup()
@@ -370,7 +368,7 @@ var/list/turret_icons
health -= force
if (force > 5 && prob(45))
spark_system.start()
spark_system.queue()
if(health <= 0)
die() //the death process :(
@@ -425,7 +423,7 @@ var/list/turret_icons
/obj/machinery/porta_turret/proc/die() //called when the turret dies, ie, health <= 0
health = 0
stat |= BROKEN //enables the BROKEN bit
spark_system.start() //creates some sparks because they look cool
spark_system.queue() //creates some sparks because they look cool
update_icon()
/obj/machinery/porta_turret/process()
+2
View File
@@ -60,6 +60,8 @@ obj/machinery/recharger/attackby(obj/item/weapon/G as obj, mob/user as mob)
return
if (istype(G, /obj/item/weapon/gun/energy/staff))
return
if (istype(G, /obj/item/weapon/gun/energy/wand))
return
if(istype(G, /obj/item/modular_computer))
var/obj/item/modular_computer/C = G
if(!C.battery_module)
+13 -16
View File
@@ -37,8 +37,7 @@ var/list/ai_status_emotions = list(
return emotions
/proc/set_ai_status_displays(mob/user as mob)
var/list/ai_emotions = get_ai_emotions(user.ckey)
var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions
var/emote = get_ai_emotion(user)
for (var/obj/machinery/M in machines) //change status
if(istype(M, /obj/machinery/ai_status_display))
var/obj/machinery/ai_status_display/AISD = M
@@ -69,26 +68,24 @@ var/list/ai_status_emotions = list(
var/emotion = "Neutral"
/obj/machinery/ai_status_display/attack_ai/(mob/user as mob)
var/list/ai_emotions = get_ai_emotions(user.ckey)
var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions
var/emote = get_ai_emotion(user)
src.emotion = emote
src.update()
/obj/machinery/ai_status_display/process()
return
/proc/get_ai_emotion(mob/user as mob)
return input(user, "Please, select a status!", "AI Status", null, null) in get_ai_emotions(user.ckey)
/obj/machinery/ai_status_display/proc/update()
if(mode==0) //Blank
overlays.Cut()
return
switch (mode)
if (0) // Blank
overlays.Cut()
if(mode==1) // AI emoticon
var/datum/ai_emotion/ai_emotion = ai_status_emotions[emotion]
set_picture(ai_emotion.overlay)
return
if (1) // AI emoticon
var/datum/ai_emotion/ai_emotion = ai_status_emotions[emotion]
set_picture(ai_emotion.overlay)
if(mode==2) // BSOD
set_picture("ai_bsod")
return
if (2) // BSOD
set_picture("ai_bsod")
/obj/machinery/ai_status_display/proc/set_picture(var/state)
picture_state = state
+3 -3
View File
@@ -170,12 +170,14 @@
idle_power_usage = 10
active_power_usage = 2000
var/obj/machinery/computer/teleporter/com
var/datum/effect_system/sparks/spark_system
/obj/machinery/teleport/hub/New()
..()
underlays.Cut()
underlays += image('icons/obj/stationobjs.dmi', icon_state = "tele-wires")
spark_system = bind_spark(src, 5, alldirs)
/obj/machinery/teleport/hub/Bumped(M as mob|obj)
spawn()
@@ -201,9 +203,7 @@
com.one_time_use = 0
com.locked = null
else
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
spark_system.queue()
accurate = 1
spawn(3000) accurate = 0 //Accurate teleporting for 5 minutes
for(var/mob/B in hearers(src, null))
+1 -1
View File
@@ -914,7 +914,7 @@
desc = "A kitchen and restaurant equipment vendor."
product_ads = "Mm, food stuffs!;Food and food accessories.;Get your plates!;You like forks?;I like forks.;Woo, utensils.;You don't really need these..."
icon_state = "dinnerware"
products = list(/obj/item/weapon/tray = 8,/obj/item/weapon/material/kitchen/utensil/fork = 6, /obj/item/weapon/material/kitchen/utensil/knife = 6, /obj/item/weapon/material/kitchen/utensil/spoon = 6, /obj/item/weapon/material/knife = 3,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 8,/obj/item/clothing/suit/chef/classic = 2)
products = list(/obj/item/weapon/tray = 8,/obj/item/weapon/material/kitchen/utensil/fork = 6, /obj/item/weapon/material/kitchen/utensil/knife = 6, /obj/item/weapon/material/kitchen/utensil/spoon = 6, /obj/item/weapon/material/knife = 3,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 8,/obj/item/clothing/suit/chef/classic = 2, /obj/item/weapon/reagent_containers/cooking_container/oven = 5, /obj/item/weapon/reagent_containers/cooking_container/fryer = 4)
contraband = list(/obj/item/weapon/material/kitchen/rollingpin = 2, /obj/item/weapon/material/knife/butch = 2)
/obj/machinery/vending/sovietsoda
+6 -6
View File
@@ -274,7 +274,7 @@
set_ready_state(0)
if(do_after_cooldown(target))
if(disabled) return
chassis.spark_system.start()
chassis.spark_system.queue()
target:ChangeTurf(/turf/simulated/floor/plating)
playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
chassis.use_power(energy_drain)
@@ -283,7 +283,7 @@
set_ready_state(0)
if(do_after_cooldown(target))
if(disabled) return
chassis.spark_system.start()
chassis.spark_system.queue()
target:ChangeTurf(get_base_turf_by_area(target))
playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
chassis.use_power(energy_drain)
@@ -292,7 +292,7 @@
set_ready_state(0)
if(do_after_cooldown(target))
if(disabled) return
chassis.spark_system.start()
chassis.spark_system.queue()
qdel(target)
playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
chassis.use_power(energy_drain)
@@ -304,7 +304,7 @@
if(disabled) return
target:ChangeTurf(/turf/simulated/floor/plating)
playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
chassis.spark_system.start()
chassis.spark_system.queue()
chassis.use_power(energy_drain*2)
else if(istype(target, /turf/simulated/floor))
occupant_message("Building Wall...")
@@ -313,7 +313,7 @@
if(disabled) return
target:ChangeTurf(/turf/simulated/wall)
playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
chassis.spark_system.start()
chassis.spark_system.queue()
chassis.use_power(energy_drain*2)
if(2)
if(istype(target, /turf/simulated/floor))
@@ -321,7 +321,7 @@
set_ready_state(0)
if(do_after_cooldown(target))
if(disabled) return
chassis.spark_system.start()
chassis.spark_system.queue()
var/obj/machinery/door/airlock/T = new /obj/machinery/door/airlock(target)
T.autoclose = 1
playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
+13 -9
View File
@@ -50,7 +50,7 @@
var/add_req_access = 1
var/maint_access = 1
var/dna //dna-locking the mech
var/datum/effect/effect/system/spark_spread/spark_system = new
var/datum/effect_system/sparks/spark_system
var/lights = 0
var/lights_power = 6
@@ -108,8 +108,6 @@
add_radio()
add_cabin()
add_airtank() //All mecha currently have airtanks. No need to check unless changes are made.
spark_system.set_up(2, 0, src)
spark_system.attach(src)
add_cell()
add_iterators()
removeVerb(/obj/mecha/verb/disconnect_from_port)
@@ -117,7 +115,8 @@
loc.Entered(src)
mechas_list += src //global mech list
narrator_message(FIRSTRUN)
return
spark_system = bind_spark(src, 2)
/obj/mecha/Destroy()
src.go_out()
@@ -595,12 +594,13 @@
/obj/mecha/proc/update_health()
if(src.health > 0)
src.spark_system.start()
src.spark_system.queue()
else
qdel(src)
return
/obj/mecha/attack_hand(mob/user as mob)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
src.log_message("Attack by hand/paw. Attacker - [user].",1)
if(istype(user,/mob/living/carbon/human))
@@ -668,7 +668,8 @@
if(istype(Proj, /obj/item/projectile/beam/pulse))
ignore_threshold = 1
src.hit_damage(Proj.damage, Proj.check_armour, is_melee=0)
if(prob(25)) spark_system.start()
if(prob(25))
spark_system.queue()
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),ignore_threshold)
//AP projectiles have a chance to cause additional damage
@@ -758,7 +759,7 @@
//////////////////////
/obj/mecha/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/mecha_parts/mecha_equipment))
var/obj/item/mecha_parts/mecha_equipment/E = W
spawn()
@@ -872,6 +873,7 @@
else
src.log_message("Attacked by [W]. Attacker - [user]")
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
if(deflect_hit(is_melee=1))
user << "<span class='danger'>\The [W] bounces off [src.name].</span>"
src.log_append_to_last("Armor saved.")
@@ -1928,7 +1930,9 @@
return icon_state
/obj/mecha/attack_generic(var/mob/user, var/damage, var/attack_message)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
if(!damage)
return 0
@@ -2248,7 +2252,7 @@
qdel(leaked_gas)
if(mecha.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT))
if(mecha.get_charge())
mecha.spark_system.start()
mecha.spark_system.queue()
mecha.cell.charge -= min(20,mecha.cell.charge)
mecha.cell.maxcharge -= min(20,mecha.cell.maxcharge)
return
@@ -71,6 +71,9 @@ var/global/list/image/splatter_cache=list()
if(amount < 1)
return
if (!blood_DNA || !islist(blood_DNA))
blood_DNA = list()
var/obj/item/organ/external/l_foot = perp.get_organ("l_foot")
var/obj/item/organ/external/r_foot = perp.get_organ("r_foot")
var/hasfeet = 1
@@ -22,9 +22,7 @@
var/obj/effect/decal/cleanable/blood/oil/streak = new(src.loc)
streak.update_icon()
else if (prob(10))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
spark(src, 3, alldirs)
if (step_to(src, get_step(src, direction), 0))
break
@@ -47,4 +45,4 @@
/obj/effect/decal/cleanable/blood/oil/streak
random_icon_states = list("mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5")
amount = 2
amount = 2
+7 -81
View File
@@ -87,82 +87,6 @@ steam.start() -- spawns the effect
spawn(20)
qdel(steam)
/////////////////////////////////////////////
//SPARK SYSTEM (like steam system)
// The attach(atom/atom) proc is optional, and can be called to attach the effect
// to something, like the RCD, so then you can just call start() and the sparks
// will always spawn at the items location.
/////////////////////////////////////////////
/obj/effect/sparks
name = "sparks"
icon = 'icons/effects/effects.dmi'
icon_state = "sparks"
var/amount = 6.0
anchored = 1.0
mouse_opacity = 0
/obj/effect/sparks/New()
..()
playsound(src.loc, "sparks", 100, 1)
var/turf/T = src.loc
if (istype(T, /turf))
T.hotspot_expose(1000,100)
/obj/effect/sparks/initialize()
..()
schedule_task_in(10 SECONDS, /proc/qdel, list(src))
/obj/effect/sparks/Destroy()
var/turf/T = src.loc
if (istype(T, /turf))
T.hotspot_expose(1000,100)
return ..()
/obj/effect/sparks/Move()
..()
var/turf/T = src.loc
if (istype(T, /turf))
T.hotspot_expose(1000,100)
/datum/effect/effect/system/spark_spread
var/total_sparks = 0 // To stop it being spammed and lagging!
set_up(n = 3, c = 0, loca)
if(n > 10)
n = 10
number = n
cardinals = c
if(istype(loca, /turf/))
location = loca
else
location = get_turf(loca)
start()
var/i = 0
for(i=0, i<src.number, i++)
if(src.total_sparks > 20)
return
spawn(0)
if(holder)
src.location = get_turf(holder)
var/obj/effect/sparks/sparks = getFromPool(/obj/effect/sparks, src.location)
src.total_sparks++
var/direction
if(src.cardinals)
direction = pick(cardinal)
else
direction = pick(alldirs)
for(i=0, i<pick(1,2,3), i++)
sleep(5)
step(sparks,direction)
spawn(20)
if(sparks)
qdel(sparks)
src.total_sparks--
/////////////////////////////////////////////
//// SMOKE SYSTEMS
// direct can be optinally added when set_up, to make the smoke always travel in one direction
@@ -184,8 +108,10 @@ steam.start() -- spawns the effect
pixel_x = -32
pixel_y = -32
/obj/effect/effect/smoke/New()
/obj/effect/effect/smoke/New(var/loc, var/duration = 0)
..()
if (duration)
time_to_live = duration
spawn (time_to_live)
qdel(src)
@@ -310,8 +236,10 @@ steam.start() -- spawns the effect
var/total_smoke = 0 // To stop it being spammed and lagging!
var/direction
var/smoke_type = /obj/effect/effect/smoke
var/smoke_duration
/datum/effect/effect/system/smoke_spread/set_up(n = 5, c = 0, loca, direct)
/datum/effect/effect/system/smoke_spread/set_up(n = 5, c = 0, loca, direct, duration = 0)
smoke_duration = duration
if(n > 10)
n = 10
number = n
@@ -475,9 +403,7 @@ steam.start() -- spawns the effect
start()
if (amount <= 2)
var/datum/effect/effect/system/spark_spread/s = getFromPool(/datum/effect/effect/system/spark_spread)
s.set_up(2, 1, location)
s.start()
spark(location, 2)
for(var/mob/M in viewers(5, location))
M << "<span class='warning'>The solution violently explodes.</span>"
+1 -3
View File
@@ -28,9 +28,7 @@
qdel(D)
if(sparks)
var/datum/effect/effect/system/spark_spread/s = getFromPool(/datum/effect/effect/system/spark_spread)
s.set_up(2, 1, get_turf(location)) // Not sure if it's safe to pass an arbitrary object to set_up, todo
s.start()
spark(location, 2, alldirs)
for(var/i = 1, i<= gibtypes.len, i++)
if(gibamounts[i])
+11 -15
View File
@@ -25,13 +25,11 @@
triggered = 1
call(src,triggerproc)(M)
/obj/effect/mine/proc/triggerrad(obj)
var/datum/effect/effect/system/spark_spread/s = getFromPool(/datum/effect/effect/system/spark_spread)
s.set_up(3, 1, src)
s.start()
obj:radiation += 50
randmutb(obj)
domutcheck(obj,null)
/obj/effect/mine/proc/triggerrad(var/mob/living/M)
spark(src, 3, alldirs)
if (istype(M))
M.apply_radiation(50)
spawn(0)
qdel(src)
@@ -39,9 +37,7 @@
if(ismob(obj))
var/mob/M = obj
M.Stun(30)
var/datum/effect/effect/system/spark_spread/s = getFromPool(/datum/effect/effect/system/spark_spread)
s.set_up(3, 1, src)
s.start()
spark(src, 3, alldirs)
spawn(0)
qdel(src)
@@ -66,11 +62,11 @@
spawn(0)
qdel(src)
/obj/effect/mine/proc/triggerkick(obj)
var/datum/effect/effect/system/spark_spread/s = getFromPool(/datum/effect/effect/system/spark_spread)
s.set_up(3, 1, src)
s.start()
qdel(obj:client)
/obj/effect/mine/proc/triggerkick(var/mob/M)
spark(src, 3, alldirs)
if (istype(M))
qdel(M.client)
spawn(0)
qdel(src)
+13 -9
View File
@@ -129,16 +129,20 @@
/obj/item/examine(mob/user, var/distance = -1)
var/size
switch(src.w_class)
if(1.0)
size = "tiny"
if(2.0)
size = "small"
if(3.0)
size = "normal-sized"
if(4.0)
size = "bulky"
if(5.0)
if (5.0 to INFINITY)
size = "huge"
if (4.0 to 5.0)
size = "bulky"
if (3.0 to 4.0)
size = "normal-sized"
if (2.0 to 3.0)
size = "small"
if (0 to 2.0)
size = "tiny"
//Changed this switch to ranges instead of tiered values, to cope with granularity and also
//things outside its range ~Nanako
return ..(user, distance, "", "It is a [size] item.")
/obj/item/attack_hand(mob/user as mob)
+7 -9
View File
@@ -12,8 +12,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
w_class = 2.0
slot_flags = SLOT_ID | SLOT_BELT
sprite_sheets = list("Resomi" = 'icons/mob/species/resomi/id.dmi')
//offset_light = 1
//diona_restricted_light = 1//Light emitted by this object or creature has limited interaction with diona
uv_intensity = 15
//Main variables
var/owner = null
@@ -344,6 +343,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
return id
/obj/item/device/pda/AltClick(var/mob/user)
if(!user || user.stat || user.lying || user.restrained() || !Adjacent(user)) return
if (ismob(src.loc))
verb_remove_id()
@@ -467,7 +467,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
pdas.Add(list(list("Name" = "[P]", "Reference" = "\ref[P]", "Detonate" = "[P.detonate]", "inconvo" = "0")))
if(8) //medical
if(P.icon_state == "pda-cmo"||P.icon_state == "pda-v"||P.icon_state == "pda-m"||P.icon_state == "pda-chem")
pdas.Add(list(list("Name" = "[P]", "Reference" = "\ref[P]", "Detonate" = "[P.detonate]", "inconvo" = "0")))
pdas.Add(list(list("Name" = "[P]", "Reference" = "\ref[P]", "Detonate" = "[P.detonate]", "inconvo" = "0")))
count++
data["convopdas"] = convopdas
@@ -730,12 +730,12 @@ var/global/list/obj/item/device/pda/PDAs = list()
active_conversation = null
if(mode==21)
mode=2
if("Filter") // Filters through available pdas
if (href_list["option"])
pdafilter = sanitize_integer(text2num(href_list["option"]), 0, 8, pdafilter)
if("Ringtone")
var/t = input(U, "Please enter new ringtone", name, ttone) as text|null
if (in_range(src, U) && loc == U)
@@ -957,9 +957,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
M.apply_effects(1,0,0,0,1)
message += "Your [P] flashes with a blinding white light! You feel weaker."
if(i>=85) //Sparks
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(2, 1, P.loc)
s.start()
spark(P.loc, 2)
message += "Your [P] begins to spark violently!"
if(i>45 && i<65 && prob(50)) //Nothing happens
message += "Your [P] bleeps loudly."
@@ -65,10 +65,7 @@
/obj/item/device/chameleon/proc/disrupt(var/delete_dummy = 1)
if(active_dummy)
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread
spark_system.set_up(5, 0, src)
spark_system.attach(src)
spark_system.start()
spark(src, 5)
eject_all()
if(delete_dummy)
qdel(active_dummy)
+23 -16
View File
@@ -8,8 +8,8 @@
flags = CONDUCT
slot_flags = SLOT_BELT
light_color = LIGHT_COLOR_HALOGEN
//offset_light = 1
//diona_restricted_light = 1//Light emitted by this object or creature has limited interaction with diona
uv_intensity = 50
light_wedge = LIGHT_WIDE
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 20)
@@ -24,10 +24,10 @@
/obj/item/device/flashlight/update_icon()
if(on)
icon_state = "[initial(icon_state)]-on"
set_light(brightness_on, update_type = UPDATE_NOW)
set_light(brightness_on)
else
icon_state = "[initial(icon_state)]"
set_light(0, update_type = UPDATE_NOW)
set_light(0)
/obj/item/device/flashlight/attack_self(mob/user)
if(!isturf(user.loc))
@@ -96,6 +96,7 @@
slot_flags = SLOT_EARS
brightness_on = 2
w_class = 1
light_wedge = LIGHT_OMNI
/obj/item/device/flashlight/drone
name = "low-power flashlight"
@@ -113,8 +114,10 @@
item_state = "heavyflashlight"
brightness_on = 4
w_class = 3
uv_intensity = 60
matter = list(DEFAULT_WALL_MATERIAL = 100,"glass" = 70)
contained_sprite = 1
light_wedge = LIGHT_SEMI
/obj/item/device/flashlight/maglight
name = "maglight"
@@ -124,10 +127,12 @@
force = 10
brightness_on = 5
w_class = 3
uv_intensity = 70
attack_verb = list("slammed", "whacked", "bashed", "thunked", "battered", "bludgeoned", "thrashed")
matter = list(DEFAULT_WALL_MATERIAL = 200,"glass" = 100)
hitsound = 'sound/weapons/smash.ogg'
contained_sprite = 1
light_wedge = LIGHT_NARROW
// the desk lamps are a bit special
@@ -137,10 +142,12 @@
icon_state = "lamp"
item_state = "lamp"
brightness_on = 5
w_class = 4
w_class = 5
flags = CONDUCT
uv_intensity = 100
on = 1
slot_flags = 0 //No wearing desklamps
light_wedge = LIGHT_OMNI
// green-shaded desk lamp
@@ -165,17 +172,17 @@
name = "flare"
desc = "A red standard-issue flare. There are instructions on the side reading 'pull cord, make light'."
w_class = 2.0
brightness_on = 8 // Pretty bright.
light_power = 3
brightness_on = 4 // Pretty bright.
light_power = 4
light_color = LIGHT_COLOR_FLARE
icon_state = "flare"
item_state = "flare"
action_button_name = null //just pull it manually, neckbeard.
var/fuel = 0
uv_intensity = 100
var/on_damage = 7
var/produce_heat = 1500
//offset_light = 0//Emits light all around, not directional
//diona_restricted_light = 0
light_wedge = LIGHT_OMNI
/obj/item/device/flashlight/flare/New()
fuel = rand(800, 1000) // Sorry for changing this so much but I keep under-estimating how long X number of ticks last in seconds.
@@ -224,14 +231,14 @@
item_state = "slime"
w_class = 1
brightness_on = 6
uv_intensity = 200
on = 1 //Bio-luminesence has one setting, on.
light_color = LIGHT_COLOR_SLIME_LAMP
//offset_light = 0//Emits light all around, not directional
//diona_restricted_light = 0
light_wedge = LIGHT_OMNI
/obj/item/device/flashlight/slime/New()
..()
set_light(brightness_on, update_type = UPDATE_NOW)
set_light(brightness_on)
/obj/item/device/flashlight/slime/update_icon()
return
@@ -252,9 +259,9 @@
icon_state = "glowstick"
item_state = "glowstick"
contained_sprite = 1
//offset_light = 0
//diona_restricted_light = 0
uv_intensity = 255
var/fuel = 0
light_wedge = LIGHT_OMNI
/obj/item/device/flashlight/glowstick/New()
fuel = rand(900, 1200)
@@ -271,7 +278,7 @@
/obj/item/device/flashlight/glowstick/proc/turn_off()
on = 0
update_icon()
/obj/item/device/flashlight/glowstick/attack_self(var/mob/living/user)
if(((CLUMSY in user.mutations)) && prob(50))
@@ -422,16 +422,7 @@
spark()
/obj/item/device/magnetic_lock/proc/spark()
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
if (target)
s.set_up(5, 1, target)
else
s.set_up(5, 1, src)
s.start()
spawn(5)
qdel(s)
spark(target ? target : src, 5, alldirs)
#undef STATUS_INACTIVE
#undef STATUS_ACTIVE
@@ -93,9 +93,7 @@
if(M)
M.moved_recently = 0
M << "<span class='danger'>You feel a sharp shock!</span>"
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, M)
s.start()
spark(M, 3)
M.Weaken(10)
@@ -169,7 +169,7 @@
valve_open = 0
if(deleted(tank_one) || deleted(tank_two) || !tank_one.air_contents || !tank_two.air_contents)
if(QDELETED(tank_one) || QDELETED(tank_two) || !tank_one.air_contents || !tank_two.air_contents)
return
var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume
@@ -104,6 +104,11 @@ A list of items and costs is stored under the datum of every game mode, alongsid
// Interaction code. Gathers a list of items purchasable from the paren't uplink and displays it. It also adds a lock button.
/obj/item/device/uplink/hidden/interact(mob/user)
ui_interact(user)
/obj/item/device/uplink/hidden/CanUseTopic()
if(!active)
return STATUS_CLOSE
return ..()
// The purchasing code.
/obj/item/device/uplink/hidden/Topic(href, href_list)

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