Master to ai electric boogaloo (#5682)

* Ports the supermatter grenade, supporting code

* May or may not make movement seem smoother

* Fixes the Sleepy Ring

* Partially ports the GLOB system

* Fixes the bug(s) that allow meat bodies to have metal brains

* ports VOREStation/VOREStation#4165 - i forgot to check if advanced who was a thing here

* Optimizes supply UI

* Transfer shuttle grammar fixes

* Fixes borked E and W fish sprites

* Fixes incorrect ETA in crew transfer announcement

* Ports descriptors from Bay

* Add files via upload

* Removes Noble Defines

* Mech Mini 'Revamp'. Will need playtesting. (#5480)

* Exosuits are now capable of holding more equipment, of specific types.

* Tweaks regarding feedback in staffside thread, other concerns.

* Tweak to be more consistent. Why did the Odysseus have two universals. Tweak to weapon restriction on Med - > Odyss

* Weapons only fit in universal combat slots.

* Adds smart magazine, magazine functionality

* Adds a new subset of grenades that shoot projectiles

* Low alpha now makes HUDs and tooltips not show up on you

* Fixes a UI bug with emptying currently-open bags into smartfridges...hopefully. (#5515)

* Update smartfridge.dm

* actually indicates which line solves the bug

* Adds a whole bunch of Exosuit weapons and other miscellaneous parts.

* Minifrags now use the small fragments mainly as they should.

* Iced beer no longer freezes you to 3 degrees C, which is enough to seriously burn a Skrell. Seriously, that's weird.

* Touch stuff in reference to responses.

* NanoUI now processes again

* Initial Work: Manifest, Newsfeed

* Adds newscast viewing, manifest

* Cartridge devices

* Template progress

* Med records, Sec records, Emp records

* Cartridge work part 1

* Cartridge work: part 2

 * Power monitoring console
 * Cartridges have persistent, internal data
 * Code to load element-specific data upon request, instead of serving all relevant data at once
 * Janitorial Supply Locator

* Refactor crew manifest to a separate file

* GPS cartridge

* Reorganize GPS to proper organization, important comments

* Supply cartridge

* Status display access

* Merc blast door controller

* Appeases travis (Round 1)

* Appeases travis (Round 2)

* Headset sprites are now on the default ear, which is left

* Cleave changes, attack code cleanup

* Catching is no longer guaranteed, accuracy code is more general

* Adds a Neural implant for future implementation. Promethean brains have been updated to fit it.

* changelog

* Robots can attack things again

* Might help with air subsystem lag

* Ports the spinny throwing animation from Bay

* Cult heal modifier no longer does Shit-Tons of agony. Does mediocre agony on non-cultists.

* Defines.

* Headset sprite tweaks

* Shield Drone no longer auto-fails with Energy Relays.

* I'm an idiot.

* PoIs can be rotated in increments of 90 degrees

* Might fix the server startup error_handler runtime

* Cult Girders are back to being proper.

* Submaps can now be rotated to any cardinal direction (South is default)

* Should fix another runtime with tools

* Buffs the Vox

* Removes debug code (Yes, I'm an idiot)

* Ready for merge

* Fixes some bugs tangentially related to Vox code

* Ports /vg/ instrument frame work, adds client based sound pref

Also shifts sound files which is 98% of the bulk here.

* Helmets now show only certain hairstyles

* fixes the trailing tag, I think

* Scrubbers no longer automatically scrub phoron (#5512)

* adds manual changelog

* Adds new set of cyborg sprites for medical/science/default/security/combat (#5546)

* Refactor cargo trains, they're just normal trains now. Adds the Quad, and re-enables/fixes the Space Bike!

* communicator_header.tmpl now correctly includes Body

* Adds tails to Unathi rig suit sprites (#5551)

* supplycom/control drops the correct circuit

* Emags have an effect on cargo consoles

* The cybersuit is now a space suit.

* Map Bugfixes

-	Fix for mislabeled c_tag cameras, first deck
-	Fix for mislabeled c_tag cameras, second deck
-	Fix for poi crashed containment shuttle mapping issues (terrain generation)
-	Fixed wrong floor type on skipjack
-	Fix for scrubbers pipe, central substation
-	Fix for air supply pipe, chapel
-	Fixed scrubber pipe, Engineering Drone Fab
-	Fix for air supply pipe, Prison Wing
-	Removed redundant supply and scrubber pipe, Security Auxiliary Dock
-	Fix, Fore Aux Dock airlock pipe.
-	Fix air supply pipe, library
-	Fix, scrubber pipe, coffee shop
-	Pipe fix, Medical maint
-	Fix, supply pipe medical secondary storage
-	Removal, redundant supply pipe, cargo maint
-	Fix, virology scrubbers pipes
-	Fix Xenobio and Xenoflora missing atmos connection to the main outpost
-	Fix, missing atmos connections between Main outpost telecoms and main outpost atmos
-	Fix for missing power wires, HoS Office, Warden Office, Heads of Staff Meeting Room
-	New, random mouse spawner
-	New, random mouse spawners added throughout maintenance on the station (maybe too many, maus station 13)
-	New, 30 sheets of lead added to engineering
-	Fix, POIs should now be rad protected and characters won’t be affected by the radiation event

* Fixes Lead Walls (#5562)

A material's ``radiation_resistance`` was never considered for calculating a wall's cached resistance to radiation. This fixes it. There is another issue involving r-walls not being better at stopping radiation than their normal-wall counterparts made of the same material but fixing that involves a lot of number adjusting to avoid the SM engine from getting twice as protective.

* Yet Another Circuit Update (#5549)

* Circuit updates, adds new components, improves printer, new assemblies.

* Finishes powernet circuit.

* Adds wearable assemblies.

* Finialization before merging with GLOB port.

* Finishes circuit update, hopefully.

* Forgot to undo map.

* Removes debug output.

* Readds size traits

* Signal pistol can be reloaded (#5566)

* Makes Blobs more useful.

* Rig and Spacesuit additions

- Added the 'military' Rigsuit from Bay.
- Added 'pmc' rigsuits
- Added exploration and pilot voidsuits along with alternate sprites (alternate sprites done by Naidh)
- Addition of suit cyclers for exploration and pilot voidsuits

None of these suits are currently accessible in game outside of admin bus. Currently only the pilot voidsuits have other species sprites. Exploration suits are missing sprites for Teshari (Naidh made some for their alternates but I have to add them) and the rig suits are human only. This is to be fixed in the near future, just wanted to get the make workload actually in the game first.

* Dermal implant doesn't cover hair

* Fixes a couple of tool related oversight/runtimes

* Fixes hand and leg cuffs

* Technically adds the Ore Redemption Machine

* Update combat.dm

* Boot knives fit in boots

* Adds tails to Unathi rigsuits (again)

* PoI fix

* Skrell names no longer contain spaces

* Descriptors now properly respect species differences

* Make the Statue NOT entirely immortal.

* Psychiatric Medication Fix (#5588)

* Psychiatric medications are faster when ingested

* Psychiatric med fix

* Updates changelog

* Tweaks emitters and Pacman

* Adds the Biopsy Scanner to the Surgery Kit (#5589)

* Adds the Biopsy Scanner to the Surgery Kit

Since it's actually used in a surgical operation, it should proooobably be in the kit. Iunno if the kit is really used here aside from antag shuttles, but they might as well have it.

* Added a missing comma

Missed a comma, might be what's causing issues. Iunno. It worked flawlessly in dream-maker.

* Adds some Holy drinks, and Promethean-safe drinks / acclimators. (#5574)

* Adds some Holy drinks, and Promethean-safe drinks / acclimators.

* Carbon + Water + Oil = Sludge

* TRUEFALSE & * removed

* Be Smart about damage things.

* Don't spawn things in Null please.

* Adds a generic proc to the mining vendor to add custom / blank entries.

* Keys now actually exist again.

* Species item slowdown changes

* Pose now shows up under descriptors

* Fixes Circuitry Glasses.

Button in HUD should work now.

* Phase rifle size correction

* Should fix the new bugs with webslinger spiders (#5612)

* Hyposprays can now have different sounds

* admin helps, but working this time.

* handle issue, GLOB staffwho

* admin list seems bork'd cleans up feedback messages

* Fixes grabs breaking defined mob pixel offsets.

Yeah.

* Custom RIG Framework (#5613)

* Framework for Custom RIG sprites.

* Fixfix

* line ending

* Text for handheld plushies when poked

Plushies now make sounds when poked. Squeak!

Ported from https://github.com/VOREStation/VOREStation/pull/4231

* Shotgun cycling animation framework
This adds the possiblity for empty sprites on all shotgun/pump/thing and for cycling animations.
https://cdn.discordapp.com/attachments/407267031562453032/488751327531368481/2018-09-10_18-43-05.gif
This particular weapon was made by a friend so i'll wait for their permission before porting it in.

* Add an animated rifle.
Nothing is particularly impressive except the animation.

* Fixes some bloodloss bugs

* Move almost everythign food related into the kitchen module.
Not moving reagents and tools.

* Minor issues fix.

* Remplace sprite hammer with pickaxe
This particular hammer had been sitting 'waiting for sprites' for 4 years at least. Could be a lot more really.

Fixeshttps://github.com/VOREStation/VOREStation/issues/4183

* Fix mislabelled posters.
https://github.com/VOREStation/VOREStation/pull/4310
https://github.com/VOREStation/VOREStation/issues/3597

* Remove kobold.dm
This file has no sprites and is used nowhere. It does have some kinda cute emotes but without sprites it's useless and has been since 2017 and maybe much longer. I haven't found any references of it's origin either.
~~maybe virgo will do sprites i dunno~~

* Fix yes emote not working correctly.
It's a lazy fix but it works.

* Fixes chem master dumping reagents.
Previously, if you used a bluespace beaker and transferred all of it's contents, the chem master buffer would silently drop all of those chemicals without warning.

* Fixed smes terminal construction requiring more cable than used.

* Fixes laptop blocking grown adults.

* Fixes several typos with oxygen_pump.dm.

* Fix the condimaster not working.
Previously, you simply couldn't make any condiment using this machine. Now you can. There was just missing template which is back in with this PR. (Thanks aronai.)
This means you should consider remplacing it in your kitchens.

* Remove intensity from chemistry machines.

* Add a noise for mining scanners.
This should affects all devices using it too.

* Prevents people from HREF exploiting around the R&D console.

* Lock has a check already, so remove that.

* reeeeeeeee

* Fixes missing sprites when excavating rocks

* Xenoflora and Xenobio House Move

- Moves Xenoflora and Xenobio stationside, on first deck. Leaves the old labs still up planetside for the time being.
- Minor bug fixes, missing lights, mislabeled lockers in robotics, floor decals.

* Changes << to to_chat at request.

* wax staxs

* Fix plastic ashtrays only holding one butt. Now they hold 4butts.
jeez bill.

* Move surgery caps into their own selection.

* Fixes maploading

Imagine you're on the last iteration of this loop, you've done the final column of X coordinates and you're going to set maxx.
Would you want to set it to where you are now, the final X column... or would you want to add ONE MORE beyond the template size for some reason then set it to that?

This bug causes all templates that are the size of normal maps to fail to initialize any atoms if your template is the size of your normal maps, because it tries to obtain a square of size minx, miny, minz, maxx, maxy, maxz to initialize, however maxx is nonextant because it exists outside the bounds of the world. It also causes all submaps to initialize an additional column of atoms twice, or not initialize any if they spawn against the right edge of the map.

* Graves (#5622)

* Adds support for closets storing closets, and graves

* More Grave Things

* Chnglog

* Polaris Vision Tweaks

* Fix a couple of ticket bugs

Don't show admin character names when they reply, and this proc appears to take different options on tg, so was fixed here.

* Prevent people from removing papers from any distances.

* Removes maintenance access from cleanbots

This should stop them from wandering into maintenance never to be seen or heard from again.

* Remove very annoying midi tools

* Magazines improvements (#5666)

* Give sounds to emptying magazines

* Clear some trash in the saber magazines

* The magazine NOW behaves correctly.

* The second half and more casing noises.

* Fixes map and makes everything compile.
This commit is contained in:
Neerti
2018-10-20 17:05:50 -04:00
committed by Atermonera
parent a7c4ac27c9
commit 88398773b8
161 changed files with 10777 additions and 8198 deletions
+24
View File
@@ -45,3 +45,27 @@
#define SMITE_BLUESPACEARTILLERY "Bluespace Artillery"
#define SMITE_SPONTANEOUSCOMBUSTION "Spontaneous Combustion"
#define SMITE_LIGHTNINGBOLT "Lightning Bolt"
#define ADMIN_QUE(user) "(<a href='?_src_=holder;adminmoreinfo=\ref[user]'>?</a>)"
#define ADMIN_FLW(user) "(<a href='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</a>)"
#define ADMIN_PP(user) "(<a href='?_src_=holder;adminplayeropts=\ref[user]'>PP</a>)"
#define ADMIN_VV(atom) "(<a href='?_src_=vars;Vars=\ref[atom]'>VV</a>)"
#define ADMIN_SM(user) "(<a href='?_src_=holder;subtlemessage=\ref[user]'>SM</a>)"
#define ADMIN_TP(user) "(<a href='?_src_=holder;traitor=\ref[user]'>TP</a>)"
#define ADMIN_BSA(user) "(<a href='?_src_=holder;BlueSpaceArtillery=\ref[user]'>BSA</a>)"
#define ADMIN_KICK(user) "(<a href='?_src_=holder;boot2=\ref[user]'>KICK</a>)"
#define ADMIN_CENTCOM_REPLY(user) "(<a href='?_src_=holder;CentcommReply=\ref[user]'>RPLY</a>)"
#define ADMIN_SYNDICATE_REPLY(user) "(<a href='?_src_=holder;SyndicateReply=\ref[user]'>RPLY</a>)"
#define ADMIN_SC(user) "(<a href='?_src_=holder;adminspawncookie=\ref[user]'>SC</a>)"
#define ADMIN_SMITE(user) "(<a href='?_src_=holder;adminsmite=\ref[user]'>SMITE</a>)"
#define ADMIN_LOOKUP(user) "[key_name_admin(user)][ADMIN_QUE(user)]"
#define ADMIN_LOOKUPFLW(user) "[key_name_admin(user)][ADMIN_QUE(user)] [ADMIN_FLW(user)]"
#define ADMIN_FULLMONTY_NONAME(user) "[ADMIN_QUE(user)] [ADMIN_PP(user)] [ADMIN_VV(user)] [ADMIN_SM(user)] [ADMIN_FLW(user)] [ADMIN_TP(user)]"
#define ADMIN_FULLMONTY(user) "[key_name_admin(user)] [ADMIN_FULLMONTY_NONAME(user)]"
#define ADMIN_JMP(src) "(<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>)"
#define COORD(src) "[src ? "([src.x],[src.y],[src.z])" : "nonexistent location"]"
#define ADMIN_COORDJMP(src) "[src ? "[COORD(src)] [ADMIN_JMP(src)]" : "nonexistent location"]"
#define AHELP_ACTIVE 1
#define AHELP_CLOSED 2
#define AHELP_RESOLVED 3
+1
View File
@@ -149,6 +149,7 @@
#define MAT_GLASS "glass"
#define MAT_SILVER "silver"
#define MAT_GOLD "gold"
#define MAT_URANIUM "uranium" //Did it
#define MAT_TITANIUM "titanium"
#define MAT_PHORON "phoron"
#define MAT_DIAMOND "diamond"
+8 -1
View File
@@ -20,4 +20,11 @@
#define QDELING(X) (X.gc_destroyed)
#define QDELETED(X) (!X || X.gc_destroyed)
#define QDESTROYING(X) (!X || X.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
#define QDESTROYING(X) (!X || X.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
#define QDEL_LIST(L) if(L) { for(var/I in L) qdel(I); L.Cut(); }
#define QDEL_LIST_ASSOC(L) if(L) { for(var/I in L) { qdel(L[I]); qdel(I); } L.Cut(); }
#define QDEL_LIST_ASSOC_VAL(L) if(L) { for(var/I in L) qdel(L[I]); L.Cut(); }
/proc/______qdel_list_wrapper(list/L) //the underscores are to encourage people not to use this directly.
QDEL_LIST(L)
+24
View File
@@ -1,3 +1,18 @@
//Timing subsystem
//Don't run if there is an identical unique timer active
#define TIMER_UNIQUE 0x1
//For unique timers: Replace the old timer rather then not start this one
#define TIMER_OVERRIDE 0x2
//Timing should be based on how timing progresses on clients, not the sever.
// tracking this is more expensive,
// should only be used in conjuction with things that have to progress client side, such as animate() or sound()
#define TIMER_CLIENT_TIME 0x4
//Timer can be stopped using deltimer()
#define TIMER_STOPPABLE 0x8
//To be used with TIMER_UNIQUE
//prevents distinguishing identical timers with the wait variable
#define TIMER_NO_HASH_WAIT 0x10
#define TIMER_NO_INVOKE_WARNING 600 //number of byond ticks that are allowed to pass before the timer subsystem thinks it hung on something
#define INITIALIZATION_INSSATOMS 0 //New should not call Initialize
#define INITIALIZATION_INNEW_MAPLOAD 1 //New should call Initialize(TRUE)
@@ -7,6 +22,15 @@
#define INITIALIZE_HINT_LATELOAD 1 //Call LateInitialize
#define INITIALIZE_HINT_QDEL 2 //Call qdel on the atom
//type and all subtypes should always call Initialize in New()
#define INITIALIZE_IMMEDIATE(X) ##X/New(loc, ...){\
..();\
if(!initialized) {\
args[1] = TRUE;\
SSatoms.InitAtom(src, args);\
}\
}
// SS runlevels
#define RUNLEVEL_INIT 0 // "Initialize Only" - Used for subsystems that should never be fired (Should also have SS_NO_FIRE set)
+6
View File
@@ -0,0 +1,6 @@
//Byond type ids
#define TYPEID_NULL "0"
#define TYPEID_NORMAL_LIST "f"
//helper macros
#define GET_TYPEID(ref) ( ( (lentext(ref) <= 10) ? "TYPEID_NULL" : copytext(ref, 4, lentext(ref)-6) ) )
#define IS_NORMAL_LIST(L) (GET_TYPEID("\ref[L]") == TYPEID_NORMAL_LIST)
+5 -1
View File
@@ -1 +1,5 @@
GLOBAL_LIST_EMPTY(all_observable_events)
GLOBAL_LIST_EMPTY(all_observable_events)
GLOBAL_VAR_INIT(timezoneOffset, 0) // The difference betwen midnight (of the host computer) and 0 world.ticks.
GLOBAL_VAR_INIT(TAB, "&nbsp;&nbsp;&nbsp;&nbsp;")
+4 -1
View File
@@ -1,2 +1,5 @@
GLOBAL_LIST_EMPTY(admins) //all clients whom are admins
GLOBAL_PROTECT(admins)
GLOBAL_PROTECT(admins)
GLOBAL_LIST_EMPTY(deadmins) //all ckeys who have used the de-admin verb.
GLOBAL_LIST_EMPTY(stealthminID)
GLOBAL_LIST_EMPTY(directory) //all ckeys with associated client
+15 -10
View File
@@ -26,17 +26,17 @@
max_z = max(z, max_z)
return max_z
/proc/get_area(O)
var/turf/loc = get_turf(O)
if(loc)
var/area/res = loc.loc
.= res
/proc/get_area(atom/A)
if(isarea(A))
return A
var/turf/T = get_turf(A)
return T ? T.loc : null
/proc/get_area_name(N) //get area by its name
for(var/area/A in all_areas)
if(A.name == N)
return A
return 0
/proc/get_area_name(atom/X, format_text = FALSE)
var/area/A = isarea(X) ? X : get_area(X)
if(!A)
return null
return format_text ? format_text(A.name) : A.name
/proc/get_area_master(const/O)
var/area/A = get_area(O)
@@ -602,3 +602,8 @@ datum/projectile_data
/proc/SecondsToTicks(var/seconds)
return seconds * 10
/proc/window_flash(var/client_or_usr)
if (!client_or_usr)
return
winset(client_or_usr, "mainwindow", "flash=5")
+11
View File
@@ -240,6 +240,17 @@ proc/listclearnulls(list/list)
for(var/i in L)
. |= i
//same, but returns nothing and acts on list in place (also handles associated values properly)
/proc/uniqueList_inplace(list/L)
var/temp = L.Copy()
L.len = 0
for(var/key in temp)
if (isnum(key))
L |= key
else
L[key] = temp[key]
//Mergesort: divides up the list into halves to begin the sort
/proc/sortKey(var/list/client/L, var/order = 1)
if(isnull(L) || L.len < 2)
+103 -1
View File
@@ -64,6 +64,11 @@ var/next_station_date_change = 1 DAY
var/time_portion = time2text(world.timeofday, "hh:mm:ss")
return "[date_portion]T[time_portion]"
/proc/gameTimestamp(format = "hh:mm:ss", wtime=null)
if(!wtime)
wtime = world.time
return time2text(wtime - GLOB.timezoneOffset, format)
/* Returns 1 if it is the selected month and day */
proc/isDay(var/month, var/day)
if(isnum(month) && isnum(day))
@@ -137,4 +142,101 @@ var/round_start_time = 0
i *= 2
while (TICK_USAGE > min(TICK_LIMIT_TO_RUN, GLOB.CURRENT_TICKLIMIT))
#undef DELTA_CALC
#undef DELTA_CALC
//Takes a value of time in deciseconds.
//Returns a text value of that number in hours, minutes, or seconds.
/proc/DisplayTimeText(time_value, truncate = FALSE)
var/second = (time_value)*0.1
var/second_adjusted = null
var/second_rounded = FALSE
var/minute = null
var/hour = null
var/day = null
if(!second)
return "0 seconds"
if(second >= 60)
minute = FLOOR(second/60, 1)
second = round(second - (minute*60), 0.1)
second_rounded = TRUE
if(second) //check if we still have seconds remaining to format, or if everything went into minute.
second_adjusted = round(second) //used to prevent '1 seconds' being shown
if(day || hour || minute)
if(second_adjusted == 1 && second >= 1)
second = " and 1 second"
else if(second > 1)
second = " and [second_adjusted] seconds"
else //shows a fraction if seconds is < 1
if(second_rounded) //no sense rounding again if it's already done
second = " and [second] seconds"
else
second = " and [round(second, 0.1)] seconds"
else
if(second_adjusted == 1 && second >= 1)
second = "[truncate ? "second" : "1 second"]"
else if(second > 1)
second = "[second_adjusted] seconds"
else
if(second_rounded)
second = "[second] seconds"
else
second = "[round(second, 0.1)] seconds"
else
second = null
if(!minute)
return "[second]"
if(minute >= 60)
hour = FLOOR(minute/60, 1)
minute = (minute - (hour*60))
if(minute) //alot simpler from here since you don't have to worry about fractions
if(minute != 1)
if((day || hour) && second)
minute = ", [minute] minutes"
else if((day || hour) && !second)
minute = " and [minute] minutes"
else
minute = "[minute] minutes"
else
if((day || hour) && second)
minute = ", 1 minute"
else if((day || hour) && !second)
minute = " and 1 minute"
else
minute = "[truncate ? "minute" : "1 minute"]"
else
minute = null
if(!hour)
return "[minute][second]"
if(hour >= 24)
day = FLOOR(hour/24, 1)
hour = (hour - (day*24))
if(hour)
if(hour != 1)
if(day && (minute || second))
hour = ", [hour] hours"
else if(day && (!minute || !second))
hour = " and [hour] hours"
else
hour = "[hour] hours"
else
if(day && (minute || second))
hour = ", 1 hour"
else if(day && (!minute || !second))
hour = " and 1 hour"
else
hour = "[truncate ? "hour" : "1 hour"]"
else
hour = null
if(!day)
return "[hour][minute][second]"
if(day > 1)
day = "[day] days"
else
day = "[truncate ? "day" : "1 day"]"
return "[day][hour][minute][second]"
+9 -1
View File
@@ -519,6 +519,14 @@ Turf and target are seperate in case you want to teleport some distance from a t
return "[round((powerused * 0.000001),0.001)] MW"
return "[round((powerused * 0.000000001),0.0001)] GW"
/proc/get_mob_by_ckey(key)
if(!key)
return
var/list/mobs = sortmobs()
for(var/mob/M in mobs)
if(M.ckey == key)
return M
//Forces a variable to be posative
/proc/modulus(var/M)
if(M >= 0)
@@ -1429,4 +1437,4 @@ var/mob/dview/dview_mob = new
return "North-Northwest"
/proc/pass()
return
return
+1 -1
View File
@@ -390,7 +390,7 @@
return 0
// Do after stuff here
user << "<span class='notice'>You start to weld the [src]..</span>"
user << "<span class='notice'>You start to weld [src]..</span>"
playsound(src.loc, WT.usesound, 50, 1)
WT.eyecheck(user)
busy = 1
@@ -20,6 +20,7 @@
/obj/machinery/computer/atmoscontrol/laptop
name = "Atmospherics Laptop"
desc = "A cheap laptop."
icon_screen = "atmoslaptop"
icon_state = "laptop"
icon_keyboard = "laptop_key"
density = 0
+1
View File
@@ -5,6 +5,7 @@
desc = "Used to view, edit and maintain medical records."
icon_keyboard = "med_key"
icon_screen = "medcomp"
density = 0 //Why does a laptop blocks peoples.
light_color = "#315ab4"
req_one_access = list(access_medical, access_forensics_lockers, access_robotics)
circuit = /obj/item/weapon/circuitboard/med_data
+4
View File
@@ -43,6 +43,8 @@
return 1
/obj/machinery/computer/supplycomp/ui_interact(mob/user, ui_key = "supply_records", var/datum/nanoui/ui = null, var/force_open = 1, var/key_state = null)
var/data[0]
var/shuttle_status[0] // Supply shuttle status
@@ -180,6 +182,8 @@
ui.set_auto_update(20) // Longer term to reduce the rate of data collection and processing
/obj/machinery/computer/supplycomp/Topic(href, href_list)
if(!supply_controller)
world.log << "## ERROR: The supply_controller datum is missing."
+1 -1
View File
@@ -205,7 +205,7 @@
var/mob/M = grab.affecting
qdel(grab)
put_mob(M)
return
/obj/machinery/atmospherics/unary/cryo_cell/MouseDrop_T(var/mob/target, var/mob/user) //Allows borgs to put people into cryo without external assistance
+9 -12
View File
@@ -33,7 +33,7 @@
if(breather.internals)
breather.internals.icon_state = "internal0"
breather.remove_from_mob(contained)
visible_message("<span class='notice'>The mask rapidly retracts just before /the [src] is destroyed!</span>")
visible_message("<span class='notice'>\The [contained] rapidly retracts just before /the [src] is destroyed!</span>")
breather = null
QDEL_NULL(tank)
@@ -45,11 +45,11 @@
if(istype(target) && CanMouseDrop(target))
if(!can_apply_to_target(target, usr)) // There is no point in attempting to apply a mask if it's impossible.
return
usr.visible_message("\The [usr] begins placing the mask onto [target]..")
usr.visible_message("\The [usr] begins placing \the [contained] onto [target].")
if(!do_mob(usr, target, 25) || !can_apply_to_target(target, usr))
return
// place mask and add fingerprints
usr.visible_message("\The [usr] has placed \the mask on [target]'s mouth.")
usr.visible_message("\The [usr] has placed \the [contained] on [target]'s mouth.")
attach_mask(target)
src.add_fingerprint(usr)
@@ -69,7 +69,7 @@
tank.forceMove(src)
breather.remove_from_mob(contained)
contained.forceMove(src)
src.visible_message("<span class='notice'>\The [user] makes \The [contained] rapidly retracts back into \the [src]!</span>")
src.visible_message("<span class='notice'>\The [user] makes \the [contained] rapidly retract back into \the [src]!</span>")
if(breather.internals)
breather.internals.icon_state = "internal0"
breather = null
@@ -112,7 +112,7 @@
to_chat(user, "<span class='warning'>There is no tank in \the [src].</span>")
return
if(stat & MAINT)
to_chat(user, "<span class='warning'>Please close \the maintenance hatch first.</span>")
to_chat(user, "<span class='warning'>Please close the maintenance hatch first.</span>")
return
if(!Adjacent(target))
to_chat(user, "<span class='warning'>Please stay close to \the [src].</span>")
@@ -123,18 +123,15 @@
return
//Checking if breather is still valid
if(target == breather && target.wear_mask != contained)
to_chat(user, "<span class='warning'>\The [target] is not using the supplied mask.</span>")
to_chat(user, "<span class='warning'>\The [target] is not using the supplied [contained].</span>")
return
return 1
/obj/machinery/oxygen_pump/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(W.is_screwdriver())
stat ^= MAINT
user.visible_message("<span class='notice'>\The [user] [stat & MAINT ? "opens" : "closes"] \the [src].</span>", "<span class='notice'>You [stat & MAINT ? "open" : "close"] \the [src].</span>")
if(stat & MAINT)
icon_state = icon_state_open
if(!stat)
icon_state = icon_state_closed
user.visible_message("<span class='notice'>\The [user] [(stat & MAINT) ? "opens" : "closes"] \the [src].</span>", "<span class='notice'>You [(stat & MAINT) ? "open" : "close"] \the [src].</span>")
icon_state = (stat & MAINT) ? icon_state_open : icon_state_closed
//TO-DO: Open icon
if(istype(W, /obj/item/weapon/tank) && (stat & MAINT))
if(tank)
@@ -151,7 +148,7 @@
/obj/machinery/oxygen_pump/examine(var/mob/user)
. = ..()
if(tank)
to_chat(user, "The meter shows [round(tank.air_contents.return_pressure())]")
to_chat(user, "The meter shows [round(tank.air_contents.return_pressure())] kPa.")
else
to_chat(user, "<span class='warning'>It is missing a tank!</span>")
@@ -0,0 +1,46 @@
/obj/effect/temp_visual/decoy
desc = "It's a decoy!"
duration = 15
/obj/effect/temp_visual/decoy/initialize(mapload, atom/mimiced_atom, var/customappearance)
. = ..()
alpha = initial(alpha)
if(mimiced_atom)
name = mimiced_atom.name
appearance = mimiced_atom.appearance
set_dir(mimiced_atom.dir)
mouse_opacity = 0
if(customappearance)
appearance = customappearance
/obj/effect/temp_visual/decoy/fading/initialize(mapload, atom/mimiced_atom)
. = ..()
animate(src, alpha = 0, time = duration)
/obj/effect/temp_visual/decoy/fading/fivesecond
duration = 50
/obj/effect/temp_visual/small_smoke
icon_state = "smoke"
duration = 50
// VOREStation Add - Used by Kinetic Accelerator
/obj/effect/temp_visual/kinetic_blast
name = "kinetic explosion"
icon = 'icons/obj/projectiles.dmi'
icon_state = "kinetic_blast"
layer = ABOVE_MOB_LAYER
duration = 4
/obj/effect/temp_visual/explosion
name = "explosion"
icon = 'icons/effects/96x96.dmi'
icon_state = "explosion"
pixel_x = -32
pixel_y = -32
duration = 8
/obj/effect/temp_visual/explosion/fast
icon_state = "explosionfast"
duration = 4
// VOREStation Add End
@@ -0,0 +1,36 @@
//temporary visual effects
/obj/effect/temp_visual
icon = 'icons/effects/effects.dmi'
icon_state = "nothing"
anchored = TRUE
layer = ABOVE_MOB_LAYER
mouse_opacity = 0
var/duration = 10 //in deciseconds
var/randomdir = TRUE
/obj/effect/temp_visual/initialize()
. = ..()
if(randomdir)
set_dir(pick(cardinal))
spawn(duration)
qdel(src)
/obj/effect/temp_visual/singularity_act()
return
/obj/effect/temp_visual/singularity_pull()
return
/obj/effect/temp_visual/ex_act()
return
/*
/obj/effect/temp_visual/dir_setting
randomdir = FALSE
/obj/effect/temp_visual/dir_setting/Initialize(mapload, set_dir)
if(set_dir)
setDir(set_dir)
. = ..()
*/ //More tg stuff that might be useful later
+33 -19
View File
@@ -111,6 +111,13 @@
src.loc = null
return ..()
// Check if target is reasonable for us to operate on.
/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self)
if(((src in target) && !target_self) || ((!istype(target.loc, /turf)) && (!istype(target, /turf)) && (not_inside)))
return FALSE
else
return TRUE
/obj/item/proc/update_twohanding()
update_held_icon()
@@ -622,7 +629,7 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
var/cannotzoom
if(usr.stat || !(istype(usr,/mob/living/carbon/human)))
if((usr.stat && !zoom) || !(istype(usr,/mob/living/carbon/human)))
usr << "You are unable to focus through the [devicename]"
cannotzoom = 1
else if(!zoom && global_hud.darkMask[1] in usr.client.screen)
@@ -632,39 +639,46 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
usr << "You are too distracted to look through the [devicename], perhaps if it was in your active hand this might work better"
cannotzoom = 1
//We checked above if they are a human and returned already if they weren't.
var/mob/living/carbon/human/H = usr
if(!zoom && !cannotzoom)
if(usr.hud_used.hud_shown)
usr.toggle_zoom_hud() // If the user has already limited their HUD this avoids them having a HUD when they zoom in
usr.client.view = viewsize
if(H.hud_used.hud_shown)
H.toggle_zoom_hud() // If the user has already limited their HUD this avoids them having a HUD when they zoom in
H.client.view = viewsize
zoom = 1
var/tilesize = 32
var/viewoffset = tilesize * tileoffset
switch(usr.dir)
switch(H.dir)
if (NORTH)
usr.client.pixel_x = 0
usr.client.pixel_y = viewoffset
H.client.pixel_x = 0
H.client.pixel_y = viewoffset
if (SOUTH)
usr.client.pixel_x = 0
usr.client.pixel_y = -viewoffset
H.client.pixel_x = 0
H.client.pixel_y = -viewoffset
if (EAST)
usr.client.pixel_x = viewoffset
usr.client.pixel_y = 0
H.client.pixel_x = viewoffset
H.client.pixel_y = 0
if (WEST)
usr.client.pixel_x = -viewoffset
usr.client.pixel_y = 0
H.client.pixel_x = -viewoffset
H.client.pixel_y = 0
usr.visible_message("[usr] peers through the [zoomdevicename ? "[zoomdevicename] of the [src.name]" : "[src.name]"].")
H.visible_message("[usr] peers through the [zoomdevicename ? "[zoomdevicename] of the [src.name]" : "[src.name]"].")
H.looking_elsewhere = TRUE
H.handle_vision()
else
usr.client.view = world.view
if(!usr.hud_used.hud_shown)
usr.toggle_zoom_hud()
H.client.view = world.view
if(!H.hud_used.hud_shown)
H.toggle_zoom_hud()
zoom = 0
usr.client.pixel_x = 0
usr.client.pixel_y = 0
H.client.pixel_x = 0
H.client.pixel_y = 0
H.looking_elsewhere = FALSE
H.handle_vision()
if(!cannotzoom)
usr.visible_message("[zoomdevicename ? "[usr] looks up from the [src.name]" : "[usr] lowers the [src.name]"].")
+46
View File
@@ -149,6 +149,52 @@
return
return ..()
/obj/item/device/kit/suit/rig
name = "rig modification kit"
desc = "A kit for modifying a rigsuit."
uses = 1
/obj/item/device/kit/suit/rig/customize(var/obj/item/I, var/mob/user)
var/obj/item/weapon/rig/RIG = I
RIG.suit_state = new_icon
RIG.suit_type = "customized [initial(RIG.suit_type)]"
RIG.name = "[new_name]"
RIG.desc = new_desc
RIG.icon = new_icon_file
RIG.icon_state = new_icon
RIG.icon_override = new_icon_override_file
for(var/obj/item/piece in list(RIG.gloves,RIG.helmet,RIG.boots,RIG.chest))
if(!istype(piece))
continue
piece.name = "[RIG.suit_type] [initial(piece.name)]"
piece.desc = "It seems to be part of a [RIG.name]."
piece.icon_state = "[RIG.suit_state]"
if(istype(piece, /obj/item/clothing/shoes))
icon = 'icons/mob/custom_items_rig_boots.dmi'
icon_override = 'icons/mob/custom_items_rig_boots.dmi'
if(istype(piece, /obj/item/clothing/suit))
icon = 'icons/mob/custom_items_rig_suit.dmi'
icon_override = 'icons/mob/custom_items_rig_suit.dmi'
if(istype(piece, /obj/item/clothing/head))
icon = 'icons/mob/custom_items_rig_helmet.dmi'
icon_override = 'icons/mob/custom_items_rig_helmet.dmi'
if(istype(piece, /obj/item/clothing/gloves))
icon = 'icons/mob/custom_items_rig_gloves.dmi'
icon_override = 'icons/mob/custom_items_rig_gloves.dmi'
if(RIG.helmet && istype(RIG.helmet, /obj/item/clothing/head/helmet) && new_light_overlay)
var/obj/item/clothing/head/helmet/H = RIG.helmet
H.light_overlay = new_light_overlay
use(1,user)
/obj/item/device/kit/suit/rig/can_customize(var/obj/item/I)
return istype(I, /obj/item/weapon/rig)
/obj/item/weapon/rig/attackby(var/obj/item/O, var/mob/user)
if(istype(O,/obj/item/device/kit/suit))
var/obj/item/device/kit/suit/rig/kit = O
kit.customize(src, user)
return
return ..()
/obj/item/device/kit/paint
name = "mecha customisation kit"
+81 -1
View File
@@ -887,6 +887,7 @@
icon_state = "nymphplushie"
w_class = ITEMSIZE_TINY
var/last_message = 0
var/pokephrase = "Uww!"
/obj/item/toy/plushie/attack_self(mob/user as mob)
if(world.time - last_message <= 1 SECOND)
@@ -899,6 +900,7 @@
user.visible_message("<span class='warning'><b>\The [user]</b> attempts to strangle [src]!</span>","<span class='warning'>You attempt to strangle [src]!</span>")
else
user.visible_message("<span class='notice'><b>\The [user]</b> pokes [src].</span>","<span class='notice'>You poke [src].</span>")
visible_message("[src] says, \"[pokephrase]\"")
last_message = world.time
/obj/item/toy/plushie/verb/rename_plushie()
@@ -926,121 +928,199 @@
name = "diona nymph plush"
desc = "A plushie of an adorable diona nymph! While its level of self-awareness is still being debated, its level of cuteness is not."
icon_state = "nymphplushie"
pokephrase = "Chirp!"
/obj/item/toy/plushie/mouse
name = "mouse plush"
desc = "A plushie of a delightful mouse! What was once considered a vile rodent is now your very best friend."
icon_state = "mouseplushie"
pokephrase = "Squeak!"
/obj/item/toy/plushie/kitten
name = "kitten plush"
desc = "A plushie of a cute kitten! Watch as it purrs its way right into your heart."
icon_state = "kittenplushie"
pokephrase = "Mrow!"
/obj/item/toy/plushie/lizard
name = "lizard plush"
desc = "A plushie of a scaly lizard! Very controversial, after being accused as \"racist\" by some Unathi."
icon_state = "lizardplushie"
pokephrase = "Hiss!"
/obj/item/toy/plushie/spider
name = "spider plush"
desc = "A plushie of a fuzzy spider! It has eight legs - all the better to hug you with."
icon_state = "spiderplushie"
pokephrase = "Sksksk!"
/obj/item/toy/plushie/farwa
name = "farwa plush"
desc = "A farwa plush doll. It's soft and comforting!"
icon_state = "farwaplushie"
pokephrase = "Squaw!"
/obj/item/toy/plushie/corgi
name = "corgi plushie"
icon_state = "corgi"
pokephrase = "Woof!"
/obj/item/toy/plushie/girly_corgi
name = "corgi plushie"
icon_state = "girlycorgi"
pokephrase = "Arf!"
/obj/item/toy/plushie/robo_corgi
name = "borgi plushie"
icon_state = "robotcorgi"
pokephrase = "Bark."
/obj/item/toy/plushie/octopus
name = "octopus plushie"
icon_state = "loveable"
pokephrase = "Squish!"
/obj/item/toy/plushie/face_hugger
name = "facehugger plushie"
icon_state = "huggable"
pokephrase = "Hug!"
//foxes are basically the best
/obj/item/toy/plushie/red_fox
name = "red fox plushie"
icon_state = "redfox"
pokephrase = "Gecker!"
/obj/item/toy/plushie/black_fox
name = "black fox plushie"
icon_state = "blackfox"
pokephrase = "Ack!"
/obj/item/toy/plushie/marble_fox
name = "marble fox plushie"
icon_state = "marblefox"
pokephrase = "Awoo!"
/obj/item/toy/plushie/blue_fox
name = "blue fox plushie"
icon_state = "bluefox"
pokephrase = "Yoww!"
/obj/item/toy/plushie/orange_fox
name = "orange fox plushie"
icon_state = "orangefox"
pokephrase = "Yagh!"
/obj/item/toy/plushie/coffee_fox
name = "coffee fox plushie"
icon_state = "coffeefox"
pokephrase = "Gerr!"
/obj/item/toy/plushie/pink_fox
name = "pink fox plushie"
icon_state = "pinkfox"
pokephrase = "Yack!"
/obj/item/toy/plushie/purple_fox
name = "purple fox plushie"
icon_state = "purplefox"
pokephrase = "Whine!"
/obj/item/toy/plushie/crimson_fox
name = "crimson fox plushie"
icon_state = "crimsonfox"
pokephrase = "Auuu!"
/obj/item/toy/plushie/deer
name = "deer plushie"
icon_state = "deer"
pokephrase = "Bleat!"
/obj/item/toy/plushie/black_cat
name = "black cat plushie"
icon_state = "blackcat"
pokephrase = "Mlem!"
/obj/item/toy/plushie/grey_cat
name = "grey cat plushie"
icon_state = "greycat"
pokephrase = "Mraw!"
/obj/item/toy/plushie/white_cat
name = "white cat plushie"
icon_state = "whitecat"
pokephrase = "Mew!"
/obj/item/toy/plushie/orange_cat
name = "orange cat plushie"
icon_state = "orangecat"
pokephrase = "Meow!"
/obj/item/toy/plushie/siamese_cat
name = "siamese cat plushie"
icon_state = "siamesecat"
pokephrase = "Mrew?"
/obj/item/toy/plushie/tabby_cat
name = "tabby cat plushie"
icon_state = "tabbycat"
pokephrase = "Purr!"
/obj/item/toy/plushie/tuxedo_cat
name = "tuxedo cat plushie"
icon_state = "tuxedocat"
pokephrase = "Mrowww!!"
// nah, squids are better than foxes :>
/obj/item/toy/plushie/squid/green
name = "green squid plushie"
desc = "A small, cute and loveable squid friend. This one is green."
icon = 'icons/obj/toy.dmi'
icon_state = "greensquid"
slot_flags = SLOT_HEAD
pokephrase = "Squrr!"
/obj/item/toy/plushie/squid/mint
name = "mint squid plushie"
desc = "A small, cute and loveable squid friend. This one is mint coloured."
icon = 'icons/obj/toy.dmi'
icon_state = "mintsquid"
slot_flags = SLOT_HEAD
pokephrase = "Blurble!"
/obj/item/toy/plushie/squid/blue
name = "blue squid plushie"
desc = "A small, cute and loveable squid friend. This one is blue."
icon = 'icons/obj/toy.dmi'
icon_state = "bluesquid"
slot_flags = SLOT_HEAD
pokephrase = "Blob!"
/obj/item/toy/plushie/squid/orange
name = "orange squid plushie"
desc = "A small, cute and loveable squid friend. This one is orange."
icon = 'icons/obj/toy.dmi'
icon_state = "orangesquid"
slot_flags = SLOT_HEAD
pokephrase = "Squash!"
/obj/item/toy/plushie/squid/yellow
name = "yellow squid plushie"
desc = "A small, cute and loveable squid friend. This one is yellow."
icon = 'icons/obj/toy.dmi'
icon_state = "yellowsquid"
slot_flags = SLOT_HEAD
pokephrase = "Glorble!"
/obj/item/toy/plushie/squid/pink
name = "pink squid plushie"
desc = "A small, cute and loveable squid friend. This one is pink."
icon = 'icons/obj/toy.dmi'
icon_state = "pinksquid"
slot_flags = SLOT_HEAD
pokephrase = "Wobble!"
// nah, squids are better than foxes :>
@@ -1322,4 +1402,4 @@
icon_state = "tinyxmastree"
w_class = ITEMSIZE_TINY
force = 1
throwforce = 1
throwforce = 1
+3 -3
View File
@@ -283,7 +283,7 @@ var/last_chew = 0
target.update_inv_legcuffed()
if(target.m_intent != "walk")
target.m_intent = "walk"
if(target.hud_used && user.hud_used.move_intent)
if(target.hud_used && target.hud_used.move_intent)
target.hud_used.move_intent.icon_state = "walking"
return 1
@@ -334,6 +334,6 @@ var/last_chew = 0
target.update_inv_legcuffed()
if(target.m_intent != "walk")
target.m_intent = "walk"
if(target.hud_used && user.hud_used.move_intent)
if(target.hud_used && target.hud_used.move_intent)
target.hud_used.move_intent.icon_state = "walking"
return 1
return 1
@@ -30,6 +30,8 @@
var/rank = null //actual job
var/dorm = 0 // determines if this ID has claimed a dorm already
var/mining_points = 0 // For redeeming at mining equipment vendors
/obj/item/weapon/card/id/examine(mob/user)
set src in oview(1)
if(in_range(usr, src))
@@ -14,7 +14,7 @@ var/global/list/ashtray_cache = list()
if(!material)
qdel(src)
return
max_butts = round(material.hardness/10) //This is arbitrary but whatever.
max_butts = round(material.hardness/5) //This is arbitrary but whatever.
src.pixel_y = rand(-5, 5)
src.pixel_x = rand(-6, 6)
update_icon()
@@ -132,7 +132,8 @@
/obj/item/weapon/surgical/FixOVein,
/obj/item/stack/medical/advanced/bruise_pack,
/obj/item/stack/nanopaste,
/obj/item/device/healthanalyzer/advanced
/obj/item/device/healthanalyzer/advanced,
/obj/item/weapon/autopsy_scanner
)
starts_with = list(
@@ -146,7 +147,8 @@
/obj/item/weapon/surgical/bonegel,
/obj/item/weapon/surgical/FixOVein,
/obj/item/stack/medical/advanced/bruise_pack,
/obj/item/device/healthanalyzer/advanced
/obj/item/device/healthanalyzer/advanced,
/obj/item/weapon/autopsy_scanner
)
/obj/item/weapon/storage/firstaid/clotting
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -201,4 +201,4 @@
return pick(prob(15);/mob/living/simple_mob/animal/passive/mouse/white,
prob(30);/mob/living/simple_mob/animal/passive/mouse/brown,
prob(30);/mob/living/simple_mob/animal/passive/mouse/gray,
prob(25);/obj/random/mouseremains) //because figuring out how to come up with it picking nothing is beyond my coding ability.
prob(25);/obj/random/mouseremains) //because figuring out how to come up with it picking nothing is beyond my coding ability.
@@ -9,18 +9,26 @@
var/icon_closed = "closed"
var/icon_opened = "open"
var/opened = 0
var/welded = 0
var/sealed = 0
var/seal_tool = /obj/item/weapon/weldingtool //Tool used to seal the closet, defaults to welder
var/wall_mounted = 0 //never solid (You can always pass over it)
var/health = 100
var/breakout = 0 //if someone is currently breaking out. mutex
var/breakout_time = 2 //2 minutes by default
var/breakout_sound = 'sound/effects/grillehit.ogg' //Sound that plays while breaking out
var/storage_capacity = 2 * MOB_MEDIUM //This is so that someone can't pack hundreds of items in a locker/crate
//then open it in a populated area to crash clients.
var/storage_cost = 40 //How much space this closet takes up if it's stuffed in another closet
var/open_sound = 'sound/machines/click.ogg'
var/close_sound = 'sound/machines/click.ogg'
var/store_misc = 1
var/store_items = 1
var/store_mobs = 1
var/store_misc = 1 //Chameleon item check
var/store_items = 1 //Will the closet store items?
var/store_mobs = 1 //Will the closet store mobs?
var/max_closets = 0 //Number of other closets allowed on tile before it won't close.
var/list/starts_with
@@ -41,7 +49,7 @@
content_size += Ceiling(I.w_class/2)
if(content_size > storage_capacity-5)
storage_capacity = content_size + 5
update_icon()
/obj/structure/closet/examine(mob/user)
if(..(user, 1) && !opened)
@@ -50,29 +58,33 @@
if(!I.anchored)
content_size += Ceiling(I.w_class/2)
if(!content_size)
user << "It is empty."
to_chat(user, "It is empty.")
else if(storage_capacity > content_size*4)
user << "It is barely filled."
to_chat(user, "It is barely filled.")
else if(storage_capacity > content_size*2)
user << "It is less than half full."
to_chat(user, "It is less than half full.")
else if(storage_capacity > content_size)
user << "There is still some free space."
to_chat(user, "There is still some free space.")
else
user << "It is full."
to_chat(user, "It is full.")
/obj/structure/closet/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0 || wall_mounted)) return 1
return (!density)
/obj/structure/closet/proc/can_open()
if(src.welded)
if(src.sealed)
return 0
return 1
/obj/structure/closet/proc/can_close()
var/closet_count = 0
for(var/obj/structure/closet/closet in get_turf(src))
if(closet != src)
return 0
if(!closet.anchored)
closet_count ++
if(closet_count > max_closets)
return 0
return 1
/obj/structure/closet/proc/dump_contents()
@@ -101,7 +113,7 @@
src.icon_state = src.icon_opened
src.opened = 1
playsound(src.loc, open_sound, 15, 1, -3)
density = 0
density = !density
return 1
/obj/structure/closet/proc/close()
@@ -118,12 +130,14 @@
stored_units += store_items(stored_units)
if(store_mobs)
stored_units += store_mobs(stored_units)
if(max_closets)
stored_units += store_closets(stored_units)
src.icon_state = src.icon_closed
src.opened = 0
playsound(src.loc, close_sound, 15, 1, -3)
density = 1
density = !density
return 1
//Cham Projector Exception
@@ -161,9 +175,25 @@
added_units += M.mob_size
return added_units
/obj/structure/closet/proc/store_closets(var/stored_units)
var/added_units = 0
for(var/obj/structure/closet/C in src.loc)
if(C == src) //Don't store ourself
continue
if(C.anchored) //Don't worry about anchored things on the same tile
continue
if(C.max_closets) //Prevents recursive storage
continue
if(stored_units + added_units + storage_cost > storage_capacity)
break
C.forceMove(src)
added_units += storage_cost
return added_units
/obj/structure/closet/proc/toggle(mob/user as mob)
if(!(src.opened ? src.close() : src.open()))
user << "<span class='notice'>It won't budge!</span>"
to_chat(user, "<span class='notice'>It won't budge!</span>")
return
update_icon()
@@ -221,7 +251,7 @@
if(!WT.isOn())
return
else
user << "<span class='notice'>You need more welding fuel to complete this task.</span>"
to_chat(user, "<span class='notice'>You need more welding fuel to complete this task.</span>")
return
playsound(src, WT.usesound, 50)
new /obj/item/stack/material/steel(src.loc)
@@ -247,21 +277,25 @@
W.forceMove(src.loc)
else if(istype(W, /obj/item/weapon/packageWrap))
return
else if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(!WT.remove_fuel(0,user))
if(!WT.isOn())
return
else
user << "<span class='notice'>You need more welding fuel to complete this task.</span>"
return
playsound(src, WT.usesound, 50)
src.welded = !src.welded
src.update_icon()
for(var/mob/M in viewers(src))
M.show_message("<span class='warning'>[src] has been [welded?"welded shut":"unwelded"] by [user.name].</span>", 3, "You hear welding.", 2)
else if(seal_tool)
if(istype(W, seal_tool))
var/obj/item/weapon/S = W
if(istype(S, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = S
if(!WT.remove_fuel(0,user))
if(!WT.isOn())
return
else
to_chat(user, "<span class='notice'>You need more welding fuel to complete this task.</span>")
return
if(do_after(user, 20 * S.toolspeed))
playsound(src, S.usesound, 50)
src.sealed = !src.sealed
src.update_icon()
for(var/mob/M in viewers(src))
M.show_message("<span class='warning'>[src] has been [sealed?"sealed":"unsealed"] by [user.name].</span>", 3)
else if(W.is_wrench())
if(welded)
if(sealed)
if(anchored)
user.visible_message("\The [user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.")
else
@@ -269,7 +303,7 @@
playsound(src, W.usesound, 50)
if(do_after(user, 20 * W.toolspeed))
if(!src) return
user << "<span class='notice'>You [anchored? "un" : ""]secured \the [src]!</span>"
to_chat(user, "<span class='notice'>You [anchored? "un" : ""]secured \the [src]!</span>")
anchored = !anchored
else
src.attack_hand(user)
@@ -305,7 +339,7 @@
return
if(!src.open())
user << "<span class='notice'>It won't budge!</span>"
to_chat(user, "<span class='notice'>It won't budge!</span>")
/obj/structure/closet/attack_hand(mob/user as mob)
src.add_fingerprint(user)
@@ -315,7 +349,7 @@
/obj/structure/closet/attack_self_tk(mob/user as mob)
src.add_fingerprint(user)
if(!src.toggle())
usr << "<span class='notice'>It won't budge!</span>"
to_chat(usr, "<span class='notice'>It won't budge!</span>")
/obj/structure/closet/attack_ghost(mob/ghost)
if(ghost.client && ghost.client.inquisitive_ghost)
@@ -335,14 +369,14 @@
src.add_fingerprint(usr)
src.toggle(usr)
else
usr << "<span class='warning'>This mob type can't use this verb.</span>"
to_chat(usr, "<span class='warning'>This mob type can't use this verb.</span>")
/obj/structure/closet/update_icon()//Putting the welded stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot)
/obj/structure/closet/update_icon()//Putting the sealed stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot)
overlays.Cut()
if(!opened)
icon_state = icon_closed
if(welded)
overlays += "welded"
if(sealed)
overlays += "sealed"
else
icon_state = icon_opened
@@ -358,20 +392,19 @@
/obj/structure/closet/proc/req_breakout()
if(opened)
return 0 //Door's open... wait, why are you in it's contents then?
if(!welded)
return 0 //closed but not welded...
if(!sealed)
return 0 //closed but not sealed...
return 1
/obj/structure/closet/proc/mob_breakout(var/mob/living/escapee)
var/breakout_time = 2 //2 minutes by default
if(breakout || !req_breakout())
return
escapee.setClickCooldown(100)
//okay, so the closet is either welded or locked... resist!!!
escapee << "<span class='warning'>You lean on the back of \the [src] and start pushing the door open. (this will take about [breakout_time] minutes)</span>"
//okay, so the closet is either sealed or locked... resist!!!
to_chat(escapee, "<span class='warning'>You lean on the back of \the [src] and start pushing the door open. (this will take about [breakout_time] minutes)</span>")
visible_message("<span class='danger'>\The [src] begins to shake violently!</span>")
@@ -388,20 +421,20 @@
breakout = 0
return
playsound(src.loc, 'sound/effects/grillehit.ogg', 100, 1)
playsound(src.loc, breakout_sound, 100, 1)
animate_shake()
add_fingerprint(escapee)
//Well then break it!
breakout = 0
escapee << "<span class='warning'>You successfully break out!</span>"
to_chat(escapee, "<span class='warning'>You successfully break out!</span>")
visible_message("<span class='danger'>\The [escapee] successfully broke out of \the [src]!</span>")
playsound(src.loc, 'sound/effects/grillehit.ogg', 100, 1)
playsound(src.loc, breakout_sound, 100, 1)
break_open()
animate_shake()
/obj/structure/closet/proc/break_open()
welded = 0
sealed = 0
update_icon()
//Do this to prevent contents from being opened into nullspace (read: bluespace)
if(istype(loc, /obj/structure/bigDelivery))
@@ -420,3 +453,9 @@
/obj/structure/closet/AllowDrop()
return TRUE
/obj/structure/closet/return_air_for_internal_lifeform(var/mob/living/L)
if(src.loc)
if(istype(src.loc, /obj/structure/closet))
return (loc.return_air_for_internal_lifeform(L))
return return_air()
@@ -4,9 +4,161 @@
icon_state = "coffin"
icon_closed = "coffin"
icon_opened = "coffin_open"
seal_tool = /obj/item/weapon/tool/screwdriver
breakout_sound = 'sound/weapons/tablehit1.ogg'
/obj/structure/closet/coffin/update_icon()
if(!opened)
icon_state = icon_closed
else
icon_state = icon_opened
/* Graves */
/obj/structure/closet/grave
name = "grave"
desc = "Dirt."
icon_state = "grave"
icon_closed = "grave"
icon_opened = "grave_open"
seal_tool = null
breakout_sound = 'sound/weapons/thudswoosh.ogg'
anchored = 1
max_closets = 1
opened = 1
/obj/structure/closet/grave/attack_hand(mob/user as mob)
if(opened)
visible_message("<span class='notice'>[user] starts to climb into \the [src.name].</span>", \
"<span class='notice'>You start to lower yourself into \the [src.name].</span>")
if(do_after(user, 50))
user.forceMove(src.loc)
visible_message("<span class='notice'>[user] climbs into \the [src.name].</span>", \
"<span class='notice'>You climb into \the [src.name].</span>")
else
visible_message("<span class='notice'>[user] decides not to climb into \the [src.name].</span>", \
"<span class='notice'>You stop climbing into \the [src.name].</span>")
return
/obj/structure/closet/grave/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(opened && ismob(mover))
var/mob/M = mover
add_fingerprint(M)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.m_intent == "walk")
to_chat(H, "<span class='warning'>You stop at the edge of \the [src.name].</span>")
return FALSE
else
to_chat(H, "<span class='warning'>You fall into \the [src.name]!</span>")
fall_in(H)
return TRUE
if(isrobot(M))
var/mob/living/silicon/robot/R = M
if(R.a_intent == I_HELP)
to_chat(R, "<span class='warning'>You stop at the edge of \the [src.name].</span>")
return FALSE
else
to_chat(R, "<span class='warning'>You enter \the [src.name].</span>")
return TRUE
return TRUE //Everything else can move over the graves
/obj/structure/closet/grave/proc/fall_in(mob/living/L) //Only called on humans for now, but still
L.Weaken(5)
if(ishuman(L))
var/mob/living/carbon/human/H = L
var/limb_damage = rand(5,25)
H.adjustBruteLoss(limb_damage)
/obj/structure/closet/grave/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(src.opened)
if(istype(W, /obj/item/weapon/shovel))
user.visible_message("<span class='notice'>[user] piles dirt into \the [src.name].</span>", \
"<span class='notice'>You start to pile dirt into \the [src.name].</span>", \
"<span class='notice'>You hear dirt being moved.</span>")
if(do_after(user, 40 * W.toolspeed))
user.visible_message("<span class='notice'>[user] pats down the dirt on top of \the [src.name].</span>", \
"<span class='notice'>You finish filling in \the [src.name].</span>")
close()
return
else
user.visible_message("<span class='notice'>[user] stops filling in \the [src.name].</span>", \
"<span class='notice'>You change your mind and stop filling in \the [src.name].</span>")
return
if(istype(W, /obj/item/weapon/grab))
var/obj/item/weapon/grab/G = W
src.MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet
return 0
if(istype(W,/obj/item/tk_grab))
return 0
if(istype(W, /obj/item/weapon/storage/laundry_basket) && W.contents.len)
var/obj/item/weapon/storage/laundry_basket/LB = W
var/turf/T = get_turf(src)
for(var/obj/item/I in LB.contents)
LB.remove_from_storage(I, T)
user.visible_message("<span class='notice'>[user] empties \the [LB] into \the [src].</span>", \
"<span class='notice'>You empty \the [LB] into \the [src].</span>", \
"<span class='notice'>You hear rustling of clothes.</span>")
return
if(isrobot(user))
return
if(W.loc != user) // This should stop mounted modules ending up outside the module.
return
usr.drop_item()
if(W)
W.forceMove(src.loc)
else
if(istype(W, /obj/item/weapon/shovel))
if(user.a_intent == I_HURT) // Hurt intent means you're trying to kill someone, or just get rid of the grave
user.visible_message("<span class='notice'>[user] begins to smoothe out the dirt of \the [src.name].</span>", \
"<span class='notice'>You start to smoothe out the dirt of \the [src.name].</span>", \
"<span class='notice'>You hear dirt being moved.</span>")
if(do_after(user, 40 * W.toolspeed))
user.visible_message("<span class='notice'>[user] finishes smoothing out \the [src.name].</span>", \
"<span class='notice'>You finish smoothing out \the [src.name].</span>")
if(LAZYLEN(contents))
alpha = 40 // If we've got stuff inside, like maybe a person, just make it hard to see us
else
qdel(src) // Else, go away
return
else
user.visible_message("<span class='notice'>[user] stops concealing \the [src.name].</span>", \
"<span class='notice'>You stop concealing \the [src.name].</span>")
return
else
user.visible_message("<span class='notice'>[user] begins to unearth \the [src.name].</span>", \
"<span class='notice'>You start to unearth \the [src.name].</span>", \
"<span class='notice'>You hear dirt being moved.</span>")
if(do_after(user, 40 * W.toolspeed))
user.visible_message("<span class='notice'>[user] reaches the bottom of \the [src.name].</span>", \
"<span class='notice'>You finish digging out \the [src.name].</span>")
break_open()
return
else
user.visible_message("<span class='notice'>[user] stops digging out \the [src.name].</span>", \
"<span class='notice'>You stop digging out \the [src.name].</span>")
return
return
/obj/structure/closet/grave/close()
..()
if(!opened)
sealed = TRUE
/obj/structure/closet/grave/open()
.=..()
alpha = 255 // Needed because of grave hiding
/obj/structure/closet/grave/bullet_act(var/obj/item/projectile/P)
return PROJECTILE_CONTINUE // It's a hole in the ground, doesn't usually stop or even care about bullets
/obj/structure/closet/grave/return_air_for_internal_lifeform(var/mob/living/L)
var/gasid = "carbon_dioxide"
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.species && H.species.exhale_type)
gasid = H.species.exhale_type
var/datum/gas_mixture/grave_breath = new()
var/datum/gas_mixture/above_air = return_air()
grave_breath.adjust_gas(gasid, BREATH_MOLES)
grave_breath.temperature = (above_air.temperature) - 30 //Underground
return grave_breath
@@ -43,8 +43,8 @@
overlays += icon(src.icon, "door")
if(welded)
overlays += icon(src.icon,"welded")
if(sealed)
overlays += icon(src.icon,"sealed")
if(broken)
overlays += icon(src.icon,"broken")
@@ -46,23 +46,23 @@
/obj/structure/closet/secure_closet/proc/togglelock(mob/user as mob)
if(src.opened)
user << "<span class='notice'>Close the locker first.</span>"
to_chat(user, "<span class='notice'>Close the locker first.</span>")
return
if(src.broken)
user << "<span class='warning'>The locker appears to be broken.</span>"
to_chat(user, "<span class='warning'>The locker appears to be broken.</span>")
return
if(user.loc == src)
user << "<span class='notice'>You can't reach the lock from inside.</span>"
to_chat(user, "<span class='notice'>You can't reach the lock from inside.</span>")
return
if(src.allowed(user))
src.locked = !src.locked
playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3)
for(var/mob/O in viewers(user, 3))
if((O.client && !( O.blinded )))
O << "<span class='notice'>The locker has been [locked ? null : "un"]locked by [user].</span>"
to_chat(O, "<span class='notice'>The locker has been [locked ? null : "un"]locked by [user].</span>")
update_icon()
else
user << "<span class='notice'>Access Denied</span>"
to_chat(user, "<span class='notice'>Access Denied</span>")
/obj/structure/closet/secure_closet/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(src.opened)
@@ -73,7 +73,7 @@
if(src.large)
src.MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet
else
user << "<span class='notice'>The locker is too small to stuff [G.affecting] into!</span>"
to_chat(user, "<span class='notice'>The locker is too small to stuff [G.affecting] into!</span>")
if(isrobot(user))
return
if(W.loc != user) // This should stop mounted modules ending up outside the module.
@@ -89,14 +89,14 @@
playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1)
playsound(src.loc, "sparks", 50, 1)
else if(W.is_wrench())
if(welded)
if(sealed)
if(anchored)
user.visible_message("\The [user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.")
else
user.visible_message("\The [user] begins securing \the [src] to the floor.", "You start securing \the [src] to the floor.")
if(do_after(user, 20 * W.toolspeed))
if(!src) return
user << "<span class='notice'>You [anchored? "un" : ""]secured \the [src]!</span>"
to_chat(user, "<span class='notice'>You [anchored? "un" : ""]secured \the [src]!</span>")
anchored = !anchored
return
else if(istype(W,/obj/item/weapon/packageWrap) || istype(W,/obj/item/weapon/weldingtool))
@@ -143,9 +143,9 @@
src.add_fingerprint(usr)
src.togglelock(usr)
else
usr << "<span class='warning'>This mob type can't use this verb.</span>"
to_chat(usr, "<span class='warning'>This mob type can't use this verb.</span>")
/obj/structure/closet/secure_closet/update_icon()//Putting the welded stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot)
/obj/structure/closet/secure_closet/update_icon()//Putting the sealed stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot)
overlays.Cut()
if(!opened)
@@ -155,8 +155,8 @@
icon_state = icon_locked
else
icon_state = icon_closed
if(welded)
overlays += "welded"
if(sealed)
overlays += "sealed"
else
icon_state = icon_opened
-2
View File
@@ -98,7 +98,6 @@
for(var/line in lines)
for(var/beat in splittext(lowertext(line), ","))
//world << "beat: [beat]"
var/list/notes = splittext(beat, "/")
for(var/note in splittext(notes[1], "-"))
if(!playing || shouldStopPlaying(user))//If the instrument is playing, or special case
@@ -106,7 +105,6 @@
return
if(lentext(note) == 0)
continue
//world << "Parse: [copytext(note,1,2)]"
var/cur_note = text2ascii(note) - 96
if(cur_note < 1 || cur_note > 7)
continue
+1 -1
View File
@@ -51,7 +51,7 @@
if(istype(spawnpoint) && den_mobs.len < max_creatures)
last_spawn = world.time
var/spawn_choice = pick(creature_types)
var/mob/living/L = new spawn_choice
var/mob/living/L = new spawn_choice(spawnpoint)
if(den_faction)
L.faction = den_faction
visible_message("<span class='warning'>\The [L] crawls out of \the [src].</span>")
+1
View File
@@ -133,6 +133,7 @@
if ("thunder") soundin = pick('sound/effects/thunder/thunder1.ogg', 'sound/effects/thunder/thunder2.ogg', 'sound/effects/thunder/thunder3.ogg', 'sound/effects/thunder/thunder4.ogg',
'sound/effects/thunder/thunder5.ogg', 'sound/effects/thunder/thunder6.ogg', 'sound/effects/thunder/thunder7.ogg', 'sound/effects/thunder/thunder8.ogg', 'sound/effects/thunder/thunder9.ogg',
'sound/effects/thunder/thunder10.ogg')
if ("casing_sound") soundin = pick('sound/weapons/casingfall1.ogg','sound/weapons/casingfall2.ogg','sound/weapons/casingfall3.ogg')
return soundin
//Are these even used?
+22 -1
View File
@@ -585,6 +585,25 @@ var/list/admin_verbs_event_manager = list(
feedback_add_details("admin_verb","OC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/findStealthKey(txt)
if(txt)
for(var/P in GLOB.stealthminID)
if(GLOB.stealthminID[P] == txt)
return P
txt = GLOB.stealthminID[ckey]
return txt
/client/proc/createStealthKey()
var/num = (rand(0,1000))
var/i = 0
while(i == 0)
i = 1
for(var/P in GLOB.stealthminID)
if(num == GLOB.stealthminID[P])
num++
i = 0
GLOB.stealthminID["[ckey]"] = "@[num2text(num)]"
/client/proc/stealth()
set category = "Admin"
set name = "Stealth Mode"
@@ -595,10 +614,12 @@ var/list/admin_verbs_event_manager = list(
mob.name = capitalize(ckey)
else
var/new_key = ckeyEx(input("Enter your desired display name.", "Fake Key", key) as text|null)
if(!new_key) return
if(!new_key)
return
if(length(new_key) >= 26)
new_key = copytext(new_key, 1, 26)
holder.fakekey = new_key
createStealthKey()
if(istype(mob, /mob/new_player))
mob.name = new_key
log_admin("[key_name(usr)] has turned stealth mode [holder.fakekey ? "ON" : "OFF"]")
+20 -2
View File
@@ -10,6 +10,20 @@
check_antagonists()
return
if(href_list["ahelp"])
if(!check_rights(R_ADMIN))
return
var/ahelp_ref = href_list["ahelp"]
var/datum/admin_help/AH = locate(ahelp_ref)
if(AH)
AH.Action(href_list["ahelp_action"])
else
to_chat(usr, "Ticket [ahelp_ref] has been deleted!")
else if(href_list["ahelp_tickets"])
GLOB.ahelp_tickets.BrowseTickets(text2num(href_list["ahelp_tickets"]))
if(href_list["dbsearchckey"] || href_list["dbsearchadmin"])
var/adminckey = href_list["dbsearchadmin"]
@@ -841,7 +855,9 @@
M << "<font color='red'>No ban appeals URL has been set.</font>"
log_admin("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.")
message_admins("<font color='blue'>[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.</font>")
var/datum/admin_help/AH = M.client ? M.client.current_ticket : null
if(AH)
AH.Resolve()
qdel(M.client)
//qdel(M) // See no reason why to delete mob. Important stuff can be lost. And ban can be lifted before round ends.
if("No")
@@ -867,7 +883,9 @@
message_admins("<font color='blue'>[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.</font>")
feedback_inc("ban_perma",1)
DB_ban_record(BANTYPE_PERMA, M, -1, reason)
var/datum/admin_help/AH = M.client ? M.client.current_ticket : null
if(AH)
AH.Resolve()
qdel(M.client)
//qdel(M)
if("Cancel")
+595 -50
View File
@@ -1,32 +1,599 @@
/client/var/datum/admin_help/current_ticket //the current ticket the (usually) not-admin client is dealing with
//This is a list of words which are ignored by the parser when comparing message contents for names. MUST BE IN LOWER CASE!
var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","alien","as")
//
//TICKET MANAGER
//
GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
/datum/admin_help_tickets
var/list/active_tickets = list()
var/list/closed_tickets = list()
var/list/resolved_tickets = list()
var/obj/effect/statclick/ticket_list/astatclick = new(null, null, AHELP_ACTIVE)
var/obj/effect/statclick/ticket_list/cstatclick = new(null, null, AHELP_CLOSED)
var/obj/effect/statclick/ticket_list/rstatclick = new(null, null, AHELP_RESOLVED)
/datum/admin_help_tickets/Destroy()
QDEL_LIST(active_tickets)
QDEL_LIST(closed_tickets)
QDEL_LIST(resolved_tickets)
QDEL_NULL(astatclick)
QDEL_NULL(cstatclick)
QDEL_NULL(rstatclick)
return ..()
//private
/datum/admin_help_tickets/proc/ListInsert(datum/admin_help/new_ticket)
var/list/ticket_list
switch(new_ticket.state)
if(AHELP_ACTIVE)
ticket_list = active_tickets
if(AHELP_CLOSED)
ticket_list = closed_tickets
if(AHELP_RESOLVED)
ticket_list = resolved_tickets
else
CRASH("Invalid ticket state: [new_ticket.state]")
var/num_closed = ticket_list.len
if(num_closed)
for(var/I in 1 to num_closed)
var/datum/admin_help/AH = ticket_list[I]
if(AH.id > new_ticket.id)
ticket_list.Insert(I, new_ticket)
return
ticket_list += new_ticket
//opens the ticket listings for one of the 3 states
/datum/admin_help_tickets/proc/BrowseTickets(state)
var/list/l2b
var/title
switch(state)
if(AHELP_ACTIVE)
l2b = active_tickets
title = "Active Tickets"
if(AHELP_CLOSED)
l2b = closed_tickets
title = "Closed Tickets"
if(AHELP_RESOLVED)
l2b = resolved_tickets
title = "Resolved Tickets"
if(!l2b)
return
var/list/dat = list("<html><head><title>[title]</title></head>")
dat += "<A HREF='?_src_=holder;ahelp_tickets=[state]'>Refresh</A><br><br>"
for(var/I in l2b)
var/datum/admin_help/AH = I
dat += "<span class='adminnotice'><span class='adminhelp'>Ticket #[AH.id]</span>: <A HREF='?_src_=holder;ahelp=\ref[AH];ahelp_action=ticket'>[AH.initiator_key_name]: [AH.name]</A></span><br>"
usr << browse(dat.Join(), "window=ahelp_list[state];size=600x480")
//Tickets statpanel
/datum/admin_help_tickets/proc/stat_entry()
var/num_disconnected = 0
stat("Active Tickets:", astatclick.update("[active_tickets.len]"))
for(var/I in active_tickets)
var/datum/admin_help/AH = I
if(AH.initiator)
stat("#[AH.id]. [AH.initiator_key_name]:", AH.statclick.update())
else
++num_disconnected
if(num_disconnected)
stat("Disconnected:", astatclick.update("[num_disconnected]"))
stat("Closed Tickets:", cstatclick.update("[closed_tickets.len]"))
stat("Resolved Tickets:", rstatclick.update("[resolved_tickets.len]"))
//Reassociate still open ticket if one exists
/datum/admin_help_tickets/proc/ClientLogin(client/C)
C.current_ticket = CKey2ActiveTicket(C.ckey)
if(C.current_ticket)
C.current_ticket.AddInteraction("Client reconnected.")
C.current_ticket.initiator = C
//Dissasociate ticket
/datum/admin_help_tickets/proc/ClientLogout(client/C)
if(C.current_ticket)
C.current_ticket.AddInteraction("Client disconnected.")
C.current_ticket.initiator = null
C.current_ticket = null
//Get a ticket given a ckey
/datum/admin_help_tickets/proc/CKey2ActiveTicket(ckey)
for(var/I in active_tickets)
var/datum/admin_help/AH = I
if(AH.initiator_ckey == ckey)
return AH
//
//TICKET LIST STATCLICK
//
/obj/effect/statclick/ticket_list
var/current_state
/obj/effect/statclick/ticket_list/New(loc, name, state)
current_state = state
..()
/obj/effect/statclick/ticket_list/Click()
GLOB.ahelp_tickets.BrowseTickets(current_state)
//
//TICKET DATUM
//
/datum/admin_help
var/id
var/name
var/state = AHELP_ACTIVE
var/opened_at
var/closed_at
var/client/initiator //semi-misnomer, it's the person who ahelped/was bwoinked
var/initiator_ckey
var/initiator_key_name
var/list/_interactions //use AddInteraction() or, preferably, admin_ticket_log()
var/obj/effect/statclick/ahelp/statclick
var/static/ticket_counter = 0
//call this on its own to create a ticket, don't manually assign current_ticket
//msg is the title of the ticket: usually the ahelp text
//is_bwoink is TRUE if this ticket was started by an admin PM
/datum/admin_help/New(msg, client/C, is_bwoink)
//clean the input msg
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
if(!msg || !C || !C.mob)
qdel(src)
return
id = ++ticket_counter
opened_at = world.time
name = msg
initiator = C
initiator_ckey = initiator.ckey
initiator_key_name = key_name(initiator, FALSE, TRUE)
if(initiator.current_ticket) //This is a bug
log_debug("Multiple ahelp current_tickets")
initiator.current_ticket.AddInteraction("Ticket erroneously left open by code")
initiator.current_ticket.Close()
initiator.current_ticket = src
var/parsed_message = keywords_lookup(msg)
statclick = new(null, src)
_interactions = list()
if(is_bwoink)
AddInteraction("<font color='blue'>[key_name_admin(usr)] PM'd [LinkedReplyName()]</font>")
message_admins("<font color='blue'>Ticket [TicketHref("#[id]")] created</font>")
else
MessageNoRecipient(parsed_message)
//show it to the person adminhelping too
to_chat(C, "<span class='adminnotice'>PM to-<b>Admins</b>: [name]</span>")
//send it to irc if nobody is on and tell us how many were on
var/admin_number_present = send2irc_adminless_only(initiator_ckey, name)
log_admin("Ticket #[id]: [key_name(initiator)]: [name] - heard by [admin_number_present] non-AFK admins who have +BAN.")
if(admin_number_present <= 0)
to_chat(C, "<span class='notice'>No active admins are online, your adminhelp was sent to the admin irc.</span>")
GLOB.ahelp_tickets.active_tickets += src
/datum/admin_help/Destroy()
RemoveActive()
GLOB.ahelp_tickets.closed_tickets -= src
GLOB.ahelp_tickets.resolved_tickets -= src
return ..()
/datum/admin_help/proc/AddInteraction(formatted_message)
_interactions += "[gameTimestamp()]: [formatted_message]"
//private
/datum/admin_help/proc/FullMonty(ref_src)
if(!ref_src)
ref_src = "\ref[src]"
. = ADMIN_FULLMONTY_NONAME(initiator.mob)
if(state == AHELP_ACTIVE)
. += ClosureLinks(ref_src)
//private
/datum/admin_help/proc/ClosureLinks(ref_src)
if(!ref_src)
ref_src = "\ref[src]"
. = " (<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=reject'>REJT</A>)"
. += " (<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=icissue'>IC</A>)"
. += " (<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=close'>CLOSE</A>)"
. += " (<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=resolve'>RSLVE</A>)"
. += " (<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=handleissue'>HANDLE</A>)"
//private
/datum/admin_help/proc/LinkedReplyName(ref_src)
if(!ref_src)
ref_src = "\ref[src]"
return "<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=reply'>[initiator_key_name]</A>"
//private
/datum/admin_help/proc/TicketHref(msg, ref_src, action = "ticket")
if(!ref_src)
ref_src = "\ref[src]"
return "<A HREF='?_src_=holder;ahelp=[ref_src];ahelp_action=[action]'>[msg]</A>"
//message from the initiator without a target, all admins will see this
//won't bug irc
/datum/admin_help/proc/MessageNoRecipient(msg)
var/ref_src = "\ref[src]"
var/chat_msg = "<span class='adminnotice'><span class='adminhelp'>Ticket [TicketHref("#[id]", ref_src)]</span><b>: [LinkedReplyName(ref_src)] [FullMonty(ref_src)]:</b> [msg]</span>"
AddInteraction("<font color='red'>[LinkedReplyName(ref_src)]: [msg]</font>")
//send this msg to all admins
for(var/client/X in admins)
if(X.is_preference_enabled(/datum/client_preference/holder/play_adminhelp_ping))
X << 'sound/effects/adminhelp.ogg'
window_flash(X)
to_chat(X, chat_msg)
//Reopen a closed ticket
/datum/admin_help/proc/Reopen()
if(state == AHELP_ACTIVE)
to_chat(usr, "<span class='warning'>This ticket is already open.</span>")
return
if(GLOB.ahelp_tickets.CKey2ActiveTicket(initiator_ckey))
to_chat(usr, "<span class='warning'>This user already has an active ticket, cannot reopen this one.</span>")
return
statclick = new(null, src)
GLOB.ahelp_tickets.active_tickets += src
GLOB.ahelp_tickets.closed_tickets -= src
GLOB.ahelp_tickets.resolved_tickets -= src
switch(state)
if(AHELP_CLOSED)
feedback_dec("ahelp_close")
if(AHELP_RESOLVED)
feedback_dec("ahelp_resolve")
state = AHELP_ACTIVE
closed_at = null
if(initiator)
initiator.current_ticket = src
AddInteraction("<font color='purple'>Reopened by [key_name_admin(usr)]</font>")
if(initiator)
to_chat(initiator, "<font color='purple'>Ticket [TicketHref("#[id]")] was reopened by [key_name(usr,FALSE,FALSE)].</font>")
var/msg = "<span class='adminhelp'>Ticket [TicketHref("#[id]")] reopened by [key_name_admin(usr)].</span>"
message_admins(msg)
log_admin(msg)
feedback_inc("ahelp_reopen")
TicketPanel() //can only be done from here, so refresh it
//private
/datum/admin_help/proc/RemoveActive()
if(state != AHELP_ACTIVE)
return
closed_at = world.time
QDEL_NULL(statclick)
GLOB.ahelp_tickets.active_tickets -= src
if(initiator && initiator.current_ticket == src)
initiator.current_ticket = null
//Mark open ticket as closed/meme
/datum/admin_help/proc/Close(silent = FALSE)
if(state != AHELP_ACTIVE)
return
RemoveActive()
state = AHELP_CLOSED
GLOB.ahelp_tickets.ListInsert(src)
AddInteraction("<font color='red'>Closed by [key_name_admin(usr)].</font>")
if(initiator)
to_chat(initiator, "<font color='red'>Ticket [TicketHref("#[id]")] was closed by [key_name(usr,FALSE,FALSE)].</font>")
if(!silent)
feedback_inc("ahelp_close")
var/msg = "Ticket [TicketHref("#[id]")] closed by [key_name_admin(usr)]."
message_admins(msg)
log_admin(msg)
//Mark open ticket as resolved/legitimate, returns ahelp verb
/datum/admin_help/proc/Resolve(silent = FALSE)
if(state != AHELP_ACTIVE)
return
RemoveActive()
state = AHELP_RESOLVED
GLOB.ahelp_tickets.ListInsert(src)
AddInteraction("<font color='green'>Resolved by [key_name_admin(usr)].</font>")
if(initiator)
to_chat(initiator, "<font color='green'>Ticket [TicketHref("#[id]")] was marked resolved by [key_name(usr,FALSE,FALSE)].</font>")
if(!silent)
feedback_inc("ahelp_resolve")
var/msg = "Ticket [TicketHref("#[id]")] resolved by [key_name_admin(usr)]"
message_admins(msg)
log_admin(msg)
//Close and return ahelp verb, use if ticket is incoherent
/datum/admin_help/proc/Reject(key_name = key_name_admin(usr))
if(state != AHELP_ACTIVE)
return
if(initiator)
initiator << 'sound/effects/adminhelp.ogg'
to_chat(initiator, "<font color='red' size='4'><b>- AdminHelp Rejected! -</b></font>")
to_chat(initiator, "<font color='red'><b>Your admin help was rejected.</b></font>")
to_chat(initiator, "Please try to be calm, clear, and descriptive in admin helps, do not assume the admin has seen any related events, and clearly state the names of anybody you are reporting.")
feedback_inc("ahelp_reject")
var/msg = "Ticket [TicketHref("#[id]")] rejected by [key_name_admin(usr)]"
message_admins(msg)
log_admin(msg)
AddInteraction("Rejected by [key_name_admin(usr)].")
Close(silent = TRUE)
//Resolve ticket with IC Issue message
/datum/admin_help/proc/ICIssue(key_name = key_name_admin(usr))
if(state != AHELP_ACTIVE)
return
var/msg = "<font color='red' size='4'><b>- AdminHelp marked as IC issue! -</b></font><br>"
msg += "<font color='red'><b>Losing is part of the game!</b></font><br>"
msg += "<font color='red'>Your AdminHelp may also be unabled to be answered due to ongoing events.</font>"
if(initiator)
to_chat(initiator, msg)
feedback_inc("ahelp_icissue")
msg = "Ticket [TicketHref("#[id]")] marked as IC by [key_name_admin(usr)]"
message_admins(msg)
log_admin(msg)
AddInteraction("Marked as IC issue by [key_name_admin(usr)]")
Resolve(silent = TRUE)
//Resolve ticket with IC Issue message
/datum/admin_help/proc/HandleIssue()
if(state != AHELP_ACTIVE)
return
var/msg = "<font color='red'>Your AdminHelp is being handled by [key_name(usr,FALSE,FALSE)] please be patient.</font>"
if(initiator)
to_chat(initiator, msg)
feedback_inc("ahelp_icissue")
msg = "Ticket [TicketHref("#[id]")] being handled by [key_name(usr,FALSE,FALSE)]"
message_admins(msg)
log_admin(msg)
AddInteraction("[key_name_admin(usr)] is now handling this ticket.")
//Show the ticket panel
/datum/admin_help/proc/TicketPanel()
var/list/dat = list("<html><head><title>Ticket #[id]</title></head>")
var/ref_src = "\ref[src]"
dat += "<h4>Admin Help Ticket #[id]: [LinkedReplyName(ref_src)]</h4>"
dat += "<b>State: "
switch(state)
if(AHELP_ACTIVE)
dat += "<font color='red'>OPEN</font>"
if(AHELP_RESOLVED)
dat += "<font color='green'>RESOLVED</font>"
if(AHELP_CLOSED)
dat += "CLOSED"
else
dat += "UNKNOWN"
dat += "</b>[GLOB.TAB][TicketHref("Refresh", ref_src)][GLOB.TAB][TicketHref("Re-Title", ref_src, "retitle")]"
if(state != AHELP_ACTIVE)
dat += "[GLOB.TAB][TicketHref("Reopen", ref_src, "reopen")]"
dat += "<br><br>Opened at: [gameTimestamp(wtime = opened_at)] (Approx [(world.time - opened_at) / 600] minutes ago)"
if(closed_at)
dat += "<br>Closed at: [gameTimestamp(wtime = closed_at)] (Approx [(world.time - closed_at) / 600] minutes ago)"
dat += "<br><br>"
if(initiator)
dat += "<b>Actions:</b> [FullMonty(ref_src)]<br>"
else
dat += "<b>DISCONNECTED</b>[GLOB.TAB][ClosureLinks(ref_src)]<br>"
dat += "<br><b>Log:</b><br><br>"
for(var/I in _interactions)
dat += "[I]<br>"
usr << browse(dat.Join(), "window=ahelp[id];size=620x480")
/datum/admin_help/proc/Retitle()
var/new_title = input(usr, "Enter a title for the ticket", "Rename Ticket", name) as text|null
if(new_title)
name = new_title
//not saying the original name cause it could be a long ass message
var/msg = "Ticket [TicketHref("#[id]")] titled [name] by [key_name_admin(usr)]"
message_admins(msg)
log_admin(msg)
TicketPanel() //we have to be here to do this
//Forwarded action from admin/Topic
/datum/admin_help/proc/Action(action)
testing("Ahelp action: [action]")
switch(action)
if("ticket")
TicketPanel()
if("retitle")
Retitle()
if("reject")
Reject()
if("reply")
usr.client.cmd_ahelp_reply(initiator)
if("icissue")
ICIssue()
if("close")
Close()
if("resolve")
Resolve()
if("handleissue")
HandleIssue()
if("reopen")
Reopen()
//
// TICKET STATCLICK
//
/obj/effect/statclick/ahelp
var/datum/admin_help/ahelp_datum
/obj/effect/statclick/ahelp/New(loc, datum/admin_help/AH)
ahelp_datum = AH
..(loc)
/obj/effect/statclick/ahelp/update()
return ..(ahelp_datum.name)
/obj/effect/statclick/ahelp/Click()
ahelp_datum.TicketPanel()
/obj/effect/statclick/ahelp/Destroy()
ahelp_datum = null
return ..()
//
// CLIENT PROCS
//
/client/verb/adminhelp(msg as text)
set category = "Admin"
set name = "Adminhelp"
if(say_disabled) //This is here to try to identify lag problems
usr << "<font color='red'>Speech is currently admin-disabled.</font>"
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
//handle muting and automuting
if(prefs.muted & MUTE_ADMINHELP)
src << "<font color='red'>Error: Admin-PM: You cannot send adminhelps (Muted).</font>"
to_chat(src, "<span class='danger'>Error: Admin-PM: You cannot send adminhelps (Muted).</span>")
return
if(handle_spam_prevention(msg,MUTE_ADMINHELP))
return
adminhelped = 1 //Determines if they get the message to reply by clicking the name.
if(msg)
handle_spam_prevention(MUTE_ADMINHELP)
//clean the input msg
if(!msg)
return
msg = sanitize(msg)
if(!msg)
//remove out adminhelp verb temporarily to prevent spamming of admins.
src.verbs -= /client/verb/adminhelp
spawn(1200)
src.verbs += /client/verb/adminhelp // 2 minute cool-down for adminhelps
feedback_add_details("admin_verb","Adminhelp") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
if(current_ticket)
if(alert(usr, "You already have a ticket open. Is this for the same issue?",,"Yes","No") != "No")
if(current_ticket)
current_ticket.MessageNoRecipient(msg)
return
else
to_chat(usr, "<span class='warning'>Ticket not found, creating new one...</span>")
else
current_ticket.AddInteraction("[key_name_admin(usr)] opened a new ticket.")
current_ticket.Close()
new /datum/admin_help(msg, src, FALSE)
//admin proc
/client/proc/cmd_admin_ticket_panel()
set name = "Show Ticket List"
set category = "Admin"
if(!check_rights(R_ADMIN, TRUE))
return
var/original_msg = msg
var/browse_to
switch(input("Display which ticket list?") as null|anything in list("Active Tickets", "Closed Tickets", "Resolved Tickets"))
if("Active Tickets")
browse_to = AHELP_ACTIVE
if("Closed Tickets")
browse_to = AHELP_CLOSED
if("Resolved Tickets")
browse_to = AHELP_RESOLVED
else
return
GLOB.ahelp_tickets.BrowseTickets(browse_to)
//
// LOGGING
//
//Use this proc when an admin takes action that may be related to an open ticket on what
//what can be a client, ckey, or mob
/proc/admin_ticket_log(what, message)
var/client/C
var/mob/Mob = what
if(istype(Mob))
C = Mob.client
else
C = what
if(istype(C) && C.current_ticket)
C.current_ticket.AddInteraction(message)
return C.current_ticket
if(istext(what)) //ckey
var/datum/admin_help/AH = GLOB.ahelp_tickets.CKey2ActiveTicket(what)
if(AH)
AH.AddInteraction(message)
return AH
//
// HELPER PROCS
//
/proc/get_admin_counts(requiredflags = R_BAN)
. = list("total" = list(), "noflags" = list(), "afk" = list(), "stealth" = list(), "present" = list())
for(var/client/X in admins)
.["total"] += X
if(requiredflags != 0 && !check_rights(rights_required = requiredflags, show_msg = FALSE, C = X))
.["noflags"] += X
else if(X.is_afk())
.["afk"] += X
else if(X.holder.fakekey)
.["stealth"] += X
else
.["present"] += X
/proc/send2irc_adminless_only(source, msg, requiredflags = R_BAN)
var/list/adm = get_admin_counts()
var/list/activemins = adm["present"]
. = activemins.len
if(. <= 0)
var/final = ""
var/list/afkmins = adm["afk"]
var/list/stealthmins = adm["stealth"]
var/list/powerlessmins = adm["noflags"]
var/list/allmins = adm["total"]
if(!afkmins.len && !stealthmins.len && !powerlessmins.len)
final = "[msg] - No admins online"
else
final = "[msg] - All admins stealthed\[[english_list(stealthmins)]\], AFK\[[english_list(afkmins)]\], or lacks +BAN\[[english_list(powerlessmins)]\]! Total: [allmins.len] "
send2irc(source,final)
/proc/ircadminwho()
var/list/message = list("Admins: ")
var/list/admin_keys = list()
for(var/adm in admins)
var/client/C = adm
admin_keys += "[C][C.holder.fakekey ? "(Stealth)" : ""][C.is_afk() ? "(AFK)" : ""]"
for(var/admin in admin_keys)
if(LAZYLEN(admin_keys) > 1)
message += ", [admin]"
else
message += "[admin]"
return jointext(message, "")
/proc/keywords_lookup(msg,irc)
//This is a list of words which are ignored by the parser when comparing message contents for names. MUST BE IN LOWER CASE!
var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","alien","as", "i")
//explode the input msg into a list
var/list/msglist = splittext(msg, " ")
@@ -35,9 +602,11 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
var/list/surnames = list()
var/list/forenames = list()
var/list/ckeys = list()
var/founds = ""
for(var/mob/M in mob_list)
var/list/indexing = list(M.real_name, M.name)
if(M.mind) indexing += M.mind.name
if(M.mind)
indexing += M.mind.name
for(var/string in indexing)
var/list/L = splittext(string, " ")
@@ -77,41 +646,17 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
mobs_found += found
if(!ai_found && isAI(found))
ai_found = 1
msg += "<b><font color='black'>[original_word] (<A HREF='?_src_=holder;adminmoreinfo=\ref[found]'>?</A>)</font></b> "
var/is_antag = 0
if(found.mind && found.mind.special_role)
is_antag = 1
founds += "Name: [found.name]([found.real_name]) Ckey: [found.ckey] [is_antag ? "(Antag)" : null] "
msg += "[original_word]<font size='1' color='[is_antag ? "red" : "black"]'>(<A HREF='?_src_=holder;adminmoreinfo=\ref[found]'>?</A>|<A HREF='?_src_=holder;adminplayerobservefollow=\ref[found]'>F</A>)</font> "
continue
msg += "[original_word] "
if(!mob) //this doesn't happen
return
var/ai_cl
if(ai_found)
ai_cl = " (<A HREF='?_src_=holder;adminchecklaws=\ref[mob]'>CL</A>)"
//Options bar: mob, details ( admin = 2, dev = 3, event manager = 4, character name (0 = just ckey, 1 = ckey and character name), link? (0 no don't make it a link, 1 do so),
// highlight special roles (0 = everyone has same looking name, 1 = antags / special roles get a golden name)
msg = "<b><font color=red>Request for Help: </font></b><font color='blue'><b>[get_options_bar(mob, 2, 1, 1)][ai_cl]</b> [msg]</font>"
var/admin_number_afk = 0
for(var/client/X in admins)
if((R_ADMIN|R_MOD|R_EVENT|R_SERVER) & X.holder.rights)
if(X.is_afk())
admin_number_afk++
X << msg
if(X.is_preference_enabled(/datum/client_preference/holder/play_adminhelp_ping))
X << 'sound/effects/adminhelp.ogg'
//show it to the person adminhelping too
src << "<font color='blue'>PM to-<b>Staff </b>: [original_msg]</font>"
var/admin_number_present = admins.len - admin_number_afk
log_admin("HELP: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins.")
if(admin_number_present <= 0)
send2adminirc("Request for Help from [key_name(src)]: [html_decode(original_msg)] - !![admin_number_afk ? "All admins AFK ([admin_number_afk])" : "No admins online"]!!")
else
send2adminirc("Request for Help from [key_name(src)]: [html_decode(original_msg)]")
feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
msg += "[original_word] "
if(irc)
if(founds == "")
return "Search Failed"
else
return founds
return msg
+12 -6
View File
@@ -109,8 +109,10 @@
if(!check_rights(R_ADMIN|R_MOD|R_DEBUG))
return
if(config.allow_admin_jump)
log_admin("[key_name(usr)] teleported [key_name(M)]")
message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)]", 1)
log_admin("[key_name(usr)] jumped to [key_name(M)]")
var/msg = "[key_name_admin(usr)] jumped to [key_name_admin(M)]"
message_admins(msg)
admin_ticket_log(M, msg)
M.on_mob_jump()
M.loc = get_turf(usr)
feedback_add_details("admin_verb","GM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -137,7 +139,9 @@
if(!M)
return
log_admin("[key_name(usr)] teleported [key_name(M)]")
message_admins("[key_name_admin(usr)] teleported [key_name(M)]", 1)
var/msg = "[key_name_admin(usr)] teleported [ADMIN_LOOKUPFLW(M)]"
message_admins(msg)
admin_ticket_log(M, msg)
if(M)
M.on_mob_jump()
M.loc = get_turf(usr)
@@ -157,7 +161,9 @@
M.loc = pick(get_area_turfs(A))
feedback_add_details("admin_verb","SMOB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] teleported [key_name(M)] to [A]")
message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)] to [A]", 1)
log_admin("[key_name(usr)] teleported [key_name(M)]")
var/msg = "[key_name_admin(usr)] teleported [ADMIN_LOOKUPFLW(M)]"
message_admins(msg)
admin_ticket_log(M, msg)
else
alert("Admin jumping disabled")
alert("Admin jumping disabled")
+234 -93
View File
@@ -1,145 +1,286 @@
#define IRCREPLYCOUNT 2
//allows right clicking mobs to send an admin PM to their client, forwards the selected mob's client to cmd_admin_pm
/client/proc/cmd_admin_pm_context(mob/M as mob in mob_list)
/client/proc/cmd_admin_pm_context(mob/M in mob_list)
set category = null
set name = "Admin PM Mob"
if(!holder)
src << "<font color='red'>Error: Admin-PM-Context: Only administrators may use this command.</font>"
to_chat(src, "<font color='red'>Error: Admin-PM-Context: Only administrators may use this command.</font>")
return
if( !ismob(M) || !M.client )
return
if( !ismob(M) || !M.client ) return
cmd_admin_pm(M.client,null)
feedback_add_details("admin_verb","APMM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
feedback_add_details("admin_verb","Admin PM Mob") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
//shows a list of clients we could send PMs to, then forwards our choice to cmd_admin_pm
/client/proc/cmd_admin_pm_panel()
set category = "Admin"
set name = "Admin PM"
if(!holder)
src << "<font color='red'>Error: Admin-PM-Panel: Only administrators may use this command.</font>"
to_chat(src, "<font color='red'>Error: Admin-PM-Panel: Only administrators may use this command.</font>")
return
var/list/client/targets[0]
for(var/client/T)
if(T.mob)
if(istype(T.mob, /mob/new_player))
if(isnewplayer(T.mob))
targets["(New Player) - [T]"] = T
else if(istype(T.mob, /mob/observer/dead))
else if(isobserver(T.mob))
targets["[T.mob.name](Ghost) - [T]"] = T
else
targets["[T.mob.real_name](as [T.mob.name]) - [T]"] = T
else
targets["(No Mob) - [T]"] = T
var/list/sorted = sortList(targets)
var/target = input(src,"To whom shall we send a message?","Admin PM",null) in sorted|null
var/target = input(src,"To whom shall we send a message?","Admin PM",null) as null|anything in sortList(targets)
cmd_admin_pm(targets[target],null)
feedback_add_details("admin_verb","APM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
feedback_add_details("admin_verb","Admin PM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_ahelp_reply(whom)
if(prefs.muted & MUTE_ADMINHELP)
to_chat(src, "<font color='red'>Error: Admin-PM: You are unable to use admin PM-s (muted).</font>")
return
var/client/C
if(istext(whom))
if(cmptext(copytext(whom,1,2),"@"))
whom = findStealthKey(whom)
C = GLOB.directory[whom]
else if(istype(whom,/client))
C = whom
if(!C)
if(holder)
to_chat(src, "<font color='red'>Error: Admin-PM: Client not found.</font>")
return
var/datum/admin_help/AH = C.current_ticket
if(AH)
message_admins("[key_name_admin(src)] has started replying to [key_name(C, 0, 0)]'s admin help.")
var/msg = input(src,"Message:", "Private message to [key_name(C, 0, 0)]") as text|null
if (!msg)
message_admins("[key_name_admin(src)] has cancelled their reply to [key_name(C, 0, 0)]'s admin help.")
return
cmd_admin_pm(whom, msg, AH)
//takes input from cmd_admin_pm_context, cmd_admin_pm_panel or /client/Topic and sends them a PM.
//Fetching a message if needed. src is the sender and C is the target client
/client/proc/cmd_admin_pm(var/client/C, var/msg = null)
/client/proc/cmd_admin_pm(whom, msg, datum/admin_help/AH)
if(prefs.muted & MUTE_ADMINHELP)
src << "<font color='red'>Error: Private-Message: You are unable to use PM-s (muted).</font>"
to_chat(src, "<font color='red'>Error: Admin-PM: You are unable to use admin PM-s (muted).</font>")
return
if(!istype(C,/client))
if(holder) src << "<font color='red'>Error: Private-Message: Client not found.</font>"
else src << "<font color='red'>Error: Private-Message: Client not found. They may have lost connection, so try using an adminhelp!</font>"
if(!holder && !current_ticket) //no ticket? https://www.youtube.com/watch?v=iHSPf6x1Fdo
to_chat(src, "<font color='red'>You can no longer reply to this ticket, please open another one by using the Adminhelp verb if need be.</font>")
to_chat(src, "<font color='blue'>Message: [msg]</font>")
return
//get message text, limit it's length.and clean/escape html
if(!msg)
msg = input(src,"Message:", "Private message to [key_name(C, 0, holder ? 1 : 0)]") as text|null
var/client/recipient
var/irc = 0
if(istext(whom))
if(cmptext(copytext(whom,1,2),"@"))
whom = findStealthKey(whom)
if(whom == "IRCKEY")
irc = 1
else
recipient = GLOB.directory[whom]
else if(istype(whom,/client))
recipient = whom
if(!msg) return
if(!C)
if(holder) src << "<font color='red'>Error: Admin-PM: Client not found.</font>"
else src << "<font color='red'>Error: Private-Message: Client not found. They may have lost connection, so try using an adminhelp!</font>"
if(irc)
if(!ircreplyamount) //to prevent people from spamming irc
return
if(!msg)
msg = input(src,"Message:", "Private message to Administrator") as text|null
if(!msg)
return
if(holder)
to_chat(src, "<font color='red'>Error: Use the admin IRC channel, nerd.</font>")
return
//clean the message if it's not sent by a high-rank admin
//todo: sanitize for all???
if(!check_rights(R_SERVER|R_DEBUG,0))
msg = sanitize(msg)
if(!msg) return
var/recieve_pm_type = "Player"
if(holder)
//mod PMs are maroon
//PMs sent from admins and mods display their rank
if(holder)
if(!C.holder && holder && holder.fakekey)
recieve_pm_type = "Admin"
else
if(!recipient)
if(holder)
to_chat(src, "<font color='red'>Error: Admin-PM: Client not found.</font>")
to_chat(src, msg)
else
recieve_pm_type = holder.rank
current_ticket.MessageNoRecipient(msg)
return
else if(!C.holder)
src << "<font color='red'>Error: Admin-PM: Non-admin to non-admin PM communication is forbidden.</font>"
return
//get message text, limit it's length.and clean/escape html
if(!msg)
msg = input(src,"Message:", "Private message to [key_name(recipient, 0, 0)]") as text|null
var/recieve_message
if(holder && !C.holder)
recieve_message = "<span class='pm'><span class='howto'><b>-- Click the [recieve_pm_type]'s name to reply --</b></span></span>\n"
if(C.adminhelped)
C << recieve_message
C.adminhelped = 0
//AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn
if(config.popup_admin_pm)
spawn(0) //so we don't hold the caller proc up
var/sender = src
var/sendername = key
var/reply = sanitize(input(C, msg,"[recieve_pm_type] PM from [sendername]", "") as text|null) //show message and await a reply
if(C && reply)
if(sender)
C.cmd_admin_pm(sender,reply) //sender is still about, let's reply to them
else
adminhelp(reply) //sender has left, adminhelp instead
if(!msg)
return
src << "<span class='pm'><span class='out'>" + create_text_tag("pm_out_alt", "PM", src) + " to <span class='name'>[get_options_bar(C, holder ? 1 : 0, holder ? 1 : 0, 1)]</span>: <span class='message'>[msg]</span></span></span>"
C << "<span class='pm'><span class='in'>" + create_text_tag("pm_in", "", C) + " <b>\[[recieve_pm_type] PM\]</b> <span class='name'>[get_options_bar(src, C.holder ? 1 : 0, C.holder ? 1 : 0, 1)]</span>: <span class='message'>[msg]</span></span></span>"
//play the recieving admin the adminhelp sound (if they have them enabled)
//non-admins shouldn't be able to disable this
if(C.is_preference_enabled(/datum/client_preference/holder/play_adminhelp_ping))
C << 'sound/effects/adminhelp.ogg'
if(prefs.muted & MUTE_ADMINHELP)
to_chat(src, "<font color='red'>Error: Admin-PM: You are unable to use admin PM-s (muted).</font>")
return
log_adminpm(msg,src,C)
send2adminirc("Reply: [key_name(src)]->[key_name(C)]: [html_decode(msg)]")
if(!recipient)
if(holder)
to_chat(src, "<font color='red'>Error: Admin-PM: Client not found.</font>")
else
current_ticket.MessageNoRecipient(msg)
return
//we don't use message_admins here because the sender/receiver might get it too
for(var/client/X in admins)
//check client/X is an admin and isn't the sender or recipient
if(X == C || X == src)
continue
if(X.key != key && X.key != C.key && (X.holder.rights & R_ADMIN|R_MOD|R_EVENT))
X << "<span class='pm'><span class='other'>" + create_text_tag("pm_other", "PM:", X) + " <span class='name'>[key_name(src, X, 0)]</span> to <span class='name'>[key_name(C, X, 0)]</span>: <span class='message'>[msg]</span></span></span>"
/client/proc/cmd_admin_irc_pm(sender)
if(prefs.muted & MUTE_ADMINHELP)
src << "<font color='red'>Error: Private-Message: You are unable to use PM-s (muted).</font>"
if (src.handle_spam_prevention(msg,MUTE_ADMINHELP))
return
var/msg = input(src,"Message:", "Reply private message to [sender] on IRC / 400 character limit") as text|null
//clean the message if it's not sent by a high-rank admin
if(!check_rights(R_SERVER|R_DEBUG,0)||irc)//no sending html to the poor bots
msg = trim(sanitize(copytext(msg,1,MAX_MESSAGE_LEN)))
if(!msg)
return
var/rawmsg = msg
var/keywordparsedmsg = keywords_lookup(msg)
if(irc)
to_chat(src, "<font color='blue'>PM to-<b>Admins</b>: [rawmsg]</font>")
admin_ticket_log(src, "<font color='red'>Reply PM from-<b>[key_name(src, TRUE, TRUE)]</b> to <i>IRC</i>: [keywordparsedmsg]</font>")
ircreplyamount--
send2irc("Reply: [ckey]",rawmsg)
else
if(recipient.holder)
if(holder) //both are admins
to_chat(recipient, "<font color='red'>Admin PM from-<b>[key_name(src, recipient, 1)]</b>: [keywordparsedmsg]</font>")
to_chat(src, "<font color='blue'>Admin PM to-<b>[key_name(recipient, src, 1)]</b>: [keywordparsedmsg]</font>")
//omg this is dumb, just fill in both their tickets
var/interaction_message = "<font color='purple'>PM from-<b>[key_name(src, recipient, 1)]</b> to-<b>[key_name(recipient, src, 1)]</b>: [keywordparsedmsg]</font>"
admin_ticket_log(src, interaction_message)
if(recipient != src) //reeee
admin_ticket_log(recipient, interaction_message)
else //recipient is an admin but sender is not
var/replymsg = "<font color='red'>Reply PM from-<b>[key_name(src, recipient, 1)]</b>: [keywordparsedmsg]</font>"
admin_ticket_log(src, replymsg)
to_chat(recipient, replymsg)
to_chat(src, "<font color='blue'>PM to-<b>Admins</b>: [msg]</font>")
//play the recieving admin the adminhelp sound (if they have them enabled)
if(recipient.is_preference_enabled(/datum/client_preference/holder/play_adminhelp_ping))
recipient << 'sound/effects/adminhelp.ogg'
else
if(holder) //sender is an admin but recipient is not. Do BIG RED TEXT
if(!recipient.current_ticket)
new /datum/admin_help(msg, recipient, TRUE)
to_chat(recipient, "<font color='red' size='4'><b>-- Administrator private message --</b></font>")
to_chat(recipient, "<font color='red'>Admin PM from-<b>[key_name(src, recipient, 0)]</b>: [msg]</font>")
to_chat(recipient, "<font color='red'><i>Click on the administrator's name to reply.</i></font>")
to_chat(src, "<font color='blue'>Admin PM to-<b>[key_name(recipient, src, 1)]</b>: [msg]</font>")
admin_ticket_log(recipient, "<font color='blue'>PM From [key_name_admin(src)]: [keywordparsedmsg]</font>")
//always play non-admin recipients the adminhelp sound
recipient << 'sound/effects/adminhelp.ogg'
//AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn
if(config.popup_admin_pm)
spawn() //so we don't hold the caller proc up
var/sender = src
var/sendername = key
var/reply = input(recipient, msg,"Admin PM from-[sendername]", "") as text|null //show message and await a reply
if(recipient && reply)
if(sender)
recipient.cmd_admin_pm(sender,reply) //sender is still about, let's reply to them
else
adminhelp(reply) //sender has left, adminhelp instead
return
else //neither are admins
to_chat(src, "<font color='red'>Error: Admin-PM: Non-admin to non-admin PM communication is forbidden.</font>")
return
if(irc)
log_admin("PM: [key_name(src)]->IRC: [rawmsg]")
for(var/client/X in admins)
to_chat(X, "<font color='blue'><B>PM: [key_name(src, X, 0)]-&gt;IRC:</B> [keywordparsedmsg]</font>")
else
log_admin("PM: [key_name(src)]->[key_name(recipient)]: [rawmsg]")
//we don't use message_admins here because the sender/receiver might get it too
for(var/client/X in admins)
if(X.key!=key && X.key!=recipient.key) //check client/X is an admin and isn't the sender or recipient
to_chat(X, "<font color='blue'><B>PM: [key_name(src, X, 0)]-&gt;[key_name(recipient, X, 0)]:</B> [keywordparsedmsg]</font>" )
/proc/IrcPm(target,msg,sender)
var/client/C = GLOB.directory[target]
var/datum/admin_help/ticket = C ? C.current_ticket : GLOB.ahelp_tickets.CKey2ActiveTicket(target)
var/compliant_msg = trim(lowertext(msg))
var/irc_tagged = "[sender](IRC)"
var/list/splits = splittext(compliant_msg, " ")
if(splits.len && splits[1] == "ticket")
if(splits.len < 2)
return "Usage: ticket <close|resolve|icissue|reject>"
switch(splits[2])
if("close")
if(ticket)
ticket.Close(irc_tagged)
return "Ticket #[ticket.id] successfully closed"
if("resolve")
if(ticket)
ticket.Resolve(irc_tagged)
return "Ticket #[ticket.id] successfully resolved"
if("icissue")
if(ticket)
ticket.ICIssue(irc_tagged)
return "Ticket #[ticket.id] successfully marked as IC issue"
if("reject")
if(ticket)
ticket.Reject(irc_tagged)
return "Ticket #[ticket.id] successfully rejected"
else
return "Usage: ticket <close|resolve|icissue|reject>"
return "Error: Ticket could not be found"
var/static/stealthkey
var/adminname = "Administrator"
if(!C)
return "Error: No client"
if(!stealthkey)
stealthkey = GenIrcStealthKey()
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
if(!msg)
return
return "Error: No message"
sanitize(msg)
message_admins("IRC message from [sender] to [key_name_admin(C)] : [msg]")
log_admin("IRC PM: [sender] -> [key_name(C)] : [msg]")
// Handled on Bot32's end, unsure about other bots
// if(length(msg) > 400) // TODO: if message length is over 400, divide it up into seperate messages, the message length restriction is based on IRC limitations. Probably easier to do this on the bots ends.
// src << "<span class='warning'>Your message was not sent because it was more then 400 characters find your message below for ease of copy/pasting</span>"
// src << "<span class='notice'>[msg]</span>"
// return
to_chat(C, "<font color='red' size='4'><b>-- Administrator private message --</b></font>")
to_chat(C, "<font color='red'>Admin PM from-<b><a href='?priv_msg=[stealthkey]'>[adminname]</A></b>: [msg]</font>")
to_chat(C, "<font color='red'><i>Click on the administrator's name to reply.</i></font>")
send2adminirc("PlayerPM to [sender] from [key_name(src)]: [html_decode(msg)]")
admin_ticket_log(C, "<font color='blue'>PM From [irc_tagged]: [msg]</font>")
src << "<span class='pm'><span class='out'>" + create_text_tag("pm_out_alt", "", src) + " to <span class='name'>IRC-[sender]</span>: <span class='message'>[msg]</span></span></span>"
window_flash(C, ignorepref = TRUE)
//always play non-admin recipients the adminhelp sound
C << 'sound/effects/adminhelp.ogg'
log_admin("PM: [key_name(src)]->IRC-[sender]: [msg]")
for(var/client/X in admins)
if(X == src)
continue
if(X.holder.rights & R_ADMIN|R_MOD)
X << "<span class='pm'><span class='other'>" + create_text_tag("pm_other", "PM:", X) + " <span class='name'>[key_name(src, X, 0)]</span> to <span class='name'>IRC-[sender]</span>: <span class='message'>[msg]</span></span></span>"
C.ircreplyamount = IRCREPLYCOUNT
return "Message Successful"
/proc/GenIrcStealthKey()
var/num = (rand(0,1000))
var/i = 0
while(i == 0)
i = 1
for(var/P in GLOB.stealthminID)
if(num == GLOB.stealthminID[P])
num++
i = 0
var/stealth = "@[num2text(num)]"
GLOB.stealthminID["IRCKEY"] = stealth
return stealth
#undef IRCREPLYCOUNT
+13 -5
View File
@@ -96,7 +96,9 @@
M << "<B>You hear a voice in your head...</B> <i>[msg]</i>"
log_admin("SubtlePM: [key_name(usr)] -> [key_name(M)] : [msg]")
message_admins("<font color='blue'><B>SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] : [msg]</B></font>", 1)
msg = "<span class='adminnotice'><b> SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] :</b> [msg]</span>"
message_admins(msg)
admin_ticket_log(M, msg)
feedback_add_details("admin_verb","SMS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_world_narrate() // Allows administrators to fluff events a little easier -- TLE
@@ -135,9 +137,11 @@
if( !msg )
return
M << msg
to_chat(M, msg)
log_admin("DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]")
message_admins("<font color='blue'><B> DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]<BR></B></font>", 1)
msg = "<span class='adminnotice'><b> DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]):</b> [msg]<BR></span>"
message_admins(msg)
admin_ticket_log(M, msg)
feedback_add_details("admin_verb","DIRN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_godmode(mob/M as mob in mob_list)
@@ -150,7 +154,9 @@
usr << "<font color='blue'> Toggled [(M.status_flags & GODMODE) ? "ON" : "OFF"]</font>"
log_admin("[key_name(usr)] has toggled [key_name(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]")
message_admins("[key_name_admin(usr)] has toggled [key_name_admin(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]", 1)
var/msg = "[key_name_admin(usr)] has toggled [ADMIN_LOOKUPFLW(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]"
message_admins(msg)
admin_ticket_log(M, msg)
feedback_add_details("admin_verb","GOD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -540,7 +546,9 @@ Traitors and the like can also be revived with the previous role mostly intact.
M.revive()
log_admin("[key_name(usr)] healed / revived [key_name(M)]")
message_admins("<font color='red'>Admin [key_name_admin(usr)] healed / revived [key_name_admin(M)]!</font>", 1)
var/msg = "<span class='danger'>Admin [key_name_admin(usr)] healed / revived [ADMIN_LOOKUPFLW(M)]!</span>"
message_admins(msg)
admin_ticket_log(M, msg)
else
alert("Admin revive disabled")
feedback_add_details("admin_verb","REJU") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+1 -1
View File
@@ -164,7 +164,7 @@
else if(istype(holder.loc, /obj/structure/closet))
var/obj/structure/closet/C = holder.loc
ai_log("handle_stance_tactical() : Inside a closet. Going to attempt escape.", AI_LOG_TRACE)
if(C.welded)
if(C.sealed)
holder.resist()
else
C.open()
+1
View File
@@ -12,6 +12,7 @@
var/last_message = "" //Contains the last message sent by this client - used to protect against copy-paste spamming.
var/last_message_count = 0 //contins a number of how many times a message identical to last_message was sent.
var/ircreplyamount = 0
/////////
//OTHER//
+4 -1
View File
@@ -57,7 +57,7 @@
if(mute_irc)
usr << "<span class='warning'You cannot use this as your client has been muted from sending messages to the admins on IRC</span>"
return
cmd_admin_irc_pm(href_list["irc_msg"])
send2adminirc(href_list["irc_msg"])
return
@@ -111,6 +111,8 @@
clients += src
directory[ckey] = src
GLOB.ahelp_tickets.ClientLogin(src)
//Admin Authorisation
holder = admin_datums[ckey]
if(holder)
@@ -176,6 +178,7 @@
if(holder)
holder.owner = null
admins -= src
GLOB.ahelp_tickets.ClientLogout(src)
directory -= ckey
clients -= src
return ..()
@@ -353,26 +353,18 @@
sols[initial(sol.name)] = sol
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(sols))
/datum/gear/head/surgical/black
display_name = "surgical cap, black"
path = /obj/item/clothing/head/surgery/black
/datum/gear/head/surgical
display_name = "surgical cap selection"
path = /obj/item/clothing/head/surgery
/datum/gear/head/surgical/blue
display_name = "surgical cap, blue"
path = /obj/item/clothing/head/surgery/blue
/datum/gear/head/surgical/green
display_name = "surgical cap, green"
path = /obj/item/clothing/head/surgery/green
/datum/gear/head/surgical/navyblue
display_name = "surgical cap, navy blue"
path = /obj/item/clothing/head/surgery/navyblue
/datum/gear/head/surgical/purple
display_name = "surgical cap, purple"
path = /obj/item/clothing/head/surgery/purple
/datum/gear/head/surgical/New()
..()
var/list/caps = list()
for(var/surgery in typesof(/obj/item/clothing/head/surgery))
var/obj/item/clothing/head/surgery/cap_type = caps
caps[initial(cap_type.name)] = cap_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(caps))
/datum/gear/head/circuitry
display_name = "headwear, circuitry (empty)"
path = /obj/item/clothing/head/circuitry
path = /obj/item/clothing/head/circuitry
+1
View File
@@ -60,6 +60,7 @@ BLIND // can't see anything
to_chat(usr, "You activate the optical matrix on the [src].")
user.update_action_buttons()
user.recalculate_vis()
..()
/obj/item/clothing/glasses/meson
name = "optical meson scanner"
+7 -4
View File
@@ -26,6 +26,8 @@
unacidable = 1
preserve_item = 1
var/suit_state //The string used for the suit's icon_state.
var/interface_path = "hardsuit.tmpl"
var/ai_interface_path = "hardsuit.tmpl"
var/interface_title = "Hardsuit Controller"
@@ -110,6 +112,7 @@
/obj/item/weapon/rig/New()
..()
suit_state = icon_state
item_state = icon_state
wires = new(src)
@@ -154,7 +157,7 @@
piece.canremove = 0
piece.name = "[suit_type] [initial(piece.name)]"
piece.desc = "It seems to be part of a [src.name]."
piece.icon_state = "[initial(icon_state)]"
piece.icon_state = "[suit_state]"
piece.min_cold_protection_temperature = min_cold_protection_temperature
piece.max_heat_protection_temperature = max_heat_protection_temperature
if(piece.siemens_coefficient > siemens_coefficient) //So that insulated gloves keep their insulation.
@@ -206,7 +209,7 @@
canremove = 1
for(var/obj/item/piece in list(helmet,boots,gloves,chest))
if(!piece) continue
piece.icon_state = "[initial(icon_state)]"
piece.icon_state = "[suit_state]"
if(airtight)
piece.item_flags &= ~(STOPPRESSUREDAMAGE|AIRTIGHT)
update_icon(1)
@@ -271,7 +274,7 @@
if(seal_delay && !instant && !do_after(M,seal_delay,needhand=0))
failed_to_seal = 1
piece.icon_state = "[initial(icon_state)][!seal_target ? "_sealed" : ""]"
piece.icon_state = "[suit_state][!seal_target ? "_sealed" : ""]"
switch(msg_type)
if("boots")
M << "<font color='blue'>\The [piece] [!seal_target ? "seal around your feet" : "relax their grip on your legs"].</font>"
@@ -309,7 +312,7 @@
qdel(booting_R)
for(var/obj/item/piece in list(helmet,boots,gloves,chest))
if(!piece) continue
piece.icon_state = "[initial(icon_state)][!seal_target ? "" : "_sealed"]"
piece.icon_state = "[suit_state][!seal_target ? "" : "_sealed"]"
canremove = !seal_target
if(airtight)
update_component_sealed()
@@ -201,6 +201,18 @@ Drinks Data
/datum/reagent/drink/nothing
glass_icon_state = "nothing"
/datum/reagent/drink/oilslick
glass_icon_state = "jar_oil"
glass_center_of_mass = list("x"=15, "y"=12)
/datum/reagent/drink/nuclearwaste
glass_icon_state = "jar_rad"
glass_center_of_mass = list("x"=15, "y"=12)
/datum/reagent/drink/sodaoil
glass_icon_state = "jar_water"
glass_center_of_mass = list("x"=15, "y"=12)
/datum/reagent/ethanol/absinthe
glass_icon_state = "absintheglass"
glass_center_of_mass = list("x"=16, "y"=5)
@@ -242,7 +254,11 @@ Drinks Data
glass_center_of_mass = list("x"=16, "y"=12)
/datum/reagent/ethanol/sake
glass_icon_state = "ginvodkaglass"
glass_icon_state = "sakecup"
glass_center_of_mass = list("x"=16, "y"=12)
/datum/reagent/ethanol/godsake
glass_icon_state = "sakeporcelain"
glass_center_of_mass = list("x"=16, "y"=12)
/datum/reagent/ethanol/tequila
@@ -502,4 +518,27 @@ Drinks Data
/datum/reagent/ethanol/specialwhiskey
glass_icon_state = "whiskeyglass"
glass_center_of_mass = list("x"=16, "y"=12)
glass_center_of_mass = list("x"=16, "y"=12)
/datum/reagent/ethanol/godka
glass_icon_state = "godkabottle"
glass_center_of_mass = list("x"=17, "y"=15)
/datum/reagent/ethanol/holywine
glass_icon_state = "holywineglass"
glass_center_of_mass = list("x"=15, "y"=7)
/datum/reagent/ethanol/holy_mary
glass_icon_state = "holymaryglass"
/datum/reagent/ethanol/angelswrath
glass_icon_state = "angelswrath"
glass_center_of_mass = list("x"=16, "y"=2)
/datum/reagent/ethanol/angelskiss
glass_icon_state = "angelskiss"
glass_center_of_mass = list("x"=16, "y"=8)
/datum/reagent/ethanol/ichor_mead
glass_icon_state = "ichor_meadglass"
glass_center_of_mass = list("x"=17, "y"=10)
@@ -1,38 +1,38 @@
#define CELLS 8
#define CELLSIZE (32/CELLS)
////////////////////////////////////////////////////////////////////////////////
/// Food.
////////////////////////////////////////////////////////////////////////////////
/obj/item/weapon/reagent_containers/food
possible_transfer_amounts = null
volume = 50 //Sets the default container amount for all food items.
var/filling_color = "#FFFFFF" //Used by sandwiches.
var/list/center_of_mass = list() // Used for table placement
/obj/item/weapon/reagent_containers/food/New()
..()
if (center_of_mass.len && !pixel_x && !pixel_y)
src.pixel_x = rand(-6.0, 6) //Randomizes postion
src.pixel_y = rand(-6.0, 6)
/obj/item/weapon/reagent_containers/food/afterattack(atom/A, mob/user, proximity, params)
if(center_of_mass.len && proximity && params && istype(A, /obj/structure/table))
//Places the item on a grid
var/list/mouse_control = params2list(params)
var/mouse_x = text2num(mouse_control["icon-x"])
var/mouse_y = text2num(mouse_control["icon-y"])
if(!isnum(mouse_x) || !isnum(mouse_y))
return
var/cell_x = max(0, min(CELLS-1, round(mouse_x/CELLSIZE)))
var/cell_y = max(0, min(CELLS-1, round(mouse_y/CELLSIZE)))
pixel_x = (CELLSIZE * (0.5 + cell_x)) - center_of_mass["x"]
pixel_y = (CELLSIZE * (0.5 + cell_y)) - center_of_mass["y"]
#undef CELLS
#undef CELLSIZE
#define CELLS 8
#define CELLSIZE (32/CELLS)
////////////////////////////////////////////////////////////////////////////////
/// Food.
////////////////////////////////////////////////////////////////////////////////
/obj/item/weapon/reagent_containers/food
possible_transfer_amounts = null
volume = 50 //Sets the default container amount for all food items.
var/filling_color = "#FFFFFF" //Used by sandwiches.
var/list/center_of_mass = list() // Used for table placement
/obj/item/weapon/reagent_containers/food/New()
..()
if (center_of_mass.len && !pixel_x && !pixel_y)
src.pixel_x = rand(-6.0, 6) //Randomizes postion
src.pixel_y = rand(-6.0, 6)
/obj/item/weapon/reagent_containers/food/afterattack(atom/A, mob/user, proximity, params)
if(center_of_mass.len && proximity && params && istype(A, /obj/structure/table))
//Places the item on a grid
var/list/mouse_control = params2list(params)
var/mouse_x = text2num(mouse_control["icon-x"])
var/mouse_y = text2num(mouse_control["icon-y"])
if(!isnum(mouse_x) || !isnum(mouse_y))
return
var/cell_x = max(0, min(CELLS-1, round(mouse_x/CELLSIZE)))
var/cell_y = max(0, min(CELLS-1, round(mouse_y/CELLSIZE)))
pixel_x = (CELLSIZE * (0.5 + cell_x)) - center_of_mass["x"]
pixel_y = (CELLSIZE * (0.5 + cell_y)) - center_of_mass["y"]
#undef CELLS
#undef CELLSIZE
@@ -1,178 +1,178 @@
///////////////////////////////////////////////Condiments
//Notes by Darem: The condiments food-subtype is for stuff you don't actually eat but you use to modify existing food. They all
// leave empty containers when used up and can be filled/re-filled with other items. Formatting for first section is identical
// to mixed-drinks code. If you want an object that starts pre-loaded, you need to make it in addition to the other code.
//Food items that aren't eaten normally and leave an empty container behind.
/obj/item/weapon/reagent_containers/food/condiment
name = "Condiment Container"
desc = "Just your average condiment container."
icon = 'icons/obj/food.dmi'
icon_state = "emptycondiment"
flags = OPENCONTAINER
possible_transfer_amounts = list(1,5,10)
center_of_mass = list("x"=16, "y"=6)
volume = 50
/obj/item/weapon/reagent_containers/food/condiment/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
return
/obj/item/weapon/reagent_containers/food/condiment/attack_self(var/mob/user as mob)
return
/obj/item/weapon/reagent_containers/food/condiment/attack(var/mob/M as mob, var/mob/user as mob, var/def_zone)
if(standard_feed_mob(user, M))
return
/obj/item/weapon/reagent_containers/food/condiment/afterattack(var/obj/target, var/mob/user, var/flag)
if(standard_dispenser_refill(user, target))
return
if(standard_pour_into(user, target))
return
if(istype(target, /obj/item/weapon/reagent_containers/food/snacks)) // These are not opencontainers but we can transfer to them
if(!reagents || !reagents.total_volume)
user << "<span class='notice'>There is no condiment left in \the [src].</span>"
return
if(!target.reagents.get_free_space())
user << "<span class='notice'>You can't add more condiment to \the [target].</span>"
return
var/trans = reagents.trans_to_obj(target, amount_per_transfer_from_this)
user << "<span class='notice'>You add [trans] units of the condiment to \the [target].</span>"
else
..()
/obj/item/weapon/reagent_containers/food/condiment/feed_sound(var/mob/user)
playsound(user.loc, 'sound/items/drink.ogg', rand(10, 50), 1)
/obj/item/weapon/reagent_containers/food/condiment/self_feed_message(var/mob/user)
user << "<span class='notice'>You swallow some of contents of \the [src].</span>"
/obj/item/weapon/reagent_containers/food/condiment/on_reagent_change()
if(reagents.reagent_list.len > 0)
switch(reagents.get_master_reagent_id())
if("ketchup")
name = "Ketchup"
desc = "You feel more American already."
icon_state = "ketchup"
center_of_mass = list("x"=16, "y"=6)
if("capsaicin")
name = "Hotsauce"
desc = "You can almost TASTE the stomach ulcers now!"
icon_state = "hotsauce"
center_of_mass = list("x"=16, "y"=6)
if("enzyme")
name = "Universal Enzyme"
desc = "Used in cooking various dishes."
icon_state = "enzyme"
center_of_mass = list("x"=16, "y"=6)
if("soysauce")
name = "Soy Sauce"
desc = "A salty soy-based flavoring."
icon_state = "soysauce"
center_of_mass = list("x"=16, "y"=6)
if("frostoil")
name = "Coldsauce"
desc = "Leaves the tongue numb in its passage."
icon_state = "coldsauce"
center_of_mass = list("x"=16, "y"=6)
if("sodiumchloride")
name = "Salt Shaker"
desc = "Salt. From space oceans, presumably."
icon_state = "saltshaker"
center_of_mass = list("x"=16, "y"=10)
if("blackpepper")
name = "Pepper Mill"
desc = "Often used to flavor food or make people sneeze."
icon_state = "peppermillsmall"
center_of_mass = list("x"=16, "y"=10)
if("cornoil")
name = "Corn Oil"
desc = "A delicious oil used in cooking. Made from corn."
icon_state = "oliveoil"
center_of_mass = list("x"=16, "y"=6)
if("sugar")
name = "Sugar"
desc = "Tastey space sugar!"
center_of_mass = list("x"=16, "y"=6)
else
name = "Misc Condiment Bottle"
if (reagents.reagent_list.len==1)
desc = "Looks like it is [reagents.get_master_reagent_name()], but you are not sure."
else
desc = "A mixture of various condiments. [reagents.get_master_reagent_name()] is one of them."
icon_state = "mixedcondiments"
center_of_mass = list("x"=16, "y"=6)
else
icon_state = "emptycondiment"
name = "Condiment Bottle"
desc = "An empty condiment bottle."
center_of_mass = list("x"=16, "y"=6)
return
/obj/item/weapon/reagent_containers/food/condiment/enzyme
name = "Universal Enzyme"
desc = "Used in cooking various dishes."
icon_state = "enzyme"
/obj/item/weapon/reagent_containers/food/condiment/enzyme/New()
..()
reagents.add_reagent("enzyme", 50)
/obj/item/weapon/reagent_containers/food/condiment/sugar/New()
..()
reagents.add_reagent("sugar", 50)
/obj/item/weapon/reagent_containers/food/condiment/small
possible_transfer_amounts = list(1,20)
amount_per_transfer_from_this = 1
volume = 20
center_of_mass = list()
/obj/item/weapon/reagent_containers/food/condiment/small/on_reagent_change()
return
/obj/item/weapon/reagent_containers/food/condiment/small/saltshaker //Seperate from above since it's a small shaker rather then
name = "salt shaker" // a large one.
desc = "Salt. From space oceans, presumably."
icon_state = "saltshakersmall"
/obj/item/weapon/reagent_containers/food/condiment/small/saltshaker/New()
..()
reagents.add_reagent("sodiumchloride", 20)
/obj/item/weapon/reagent_containers/food/condiment/small/peppermill
name = "pepper mill"
desc = "Often used to flavor food or make people sneeze."
icon_state = "peppermillsmall"
/obj/item/weapon/reagent_containers/food/condiment/small/peppermill/New()
..()
reagents.add_reagent("blackpepper", 20)
/obj/item/weapon/reagent_containers/food/condiment/small/sugar
name = "sugar"
desc = "Sweetness in a bottle"
icon_state = "sugarsmall"
/obj/item/weapon/reagent_containers/food/condiment/small/sugar/New()
..()
reagents.add_reagent("sugar", 20)
/obj/item/weapon/reagent_containers/food/condiment/flour
name = "flour sack"
desc = "A big bag of flour. Good for baking!"
icon = 'icons/obj/food.dmi'
icon_state = "flour"
/obj/item/weapon/reagent_containers/food/condiment/flour/on_reagent_change()
return
/obj/item/weapon/reagent_containers/food/condiment/flour/New()
..()
reagents.add_reagent("flour", 30)
src.pixel_x = rand(-10.0, 10)
src.pixel_y = rand(-10.0, 10)
///////////////////////////////////////////////Condiments
//Notes by Darem: The condiments food-subtype is for stuff you don't actually eat but you use to modify existing food. They all
// leave empty containers when used up and can be filled/re-filled with other items. Formatting for first section is identical
// to mixed-drinks code. If you want an object that starts pre-loaded, you need to make it in addition to the other code.
//Food items that aren't eaten normally and leave an empty container behind.
/obj/item/weapon/reagent_containers/food/condiment
name = "Condiment Container"
desc = "Just your average condiment container."
icon = 'icons/obj/food.dmi'
icon_state = "emptycondiment"
flags = OPENCONTAINER
possible_transfer_amounts = list(1,5,10)
center_of_mass = list("x"=16, "y"=6)
volume = 50
/obj/item/weapon/reagent_containers/food/condiment/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
return
/obj/item/weapon/reagent_containers/food/condiment/attack_self(var/mob/user as mob)
return
/obj/item/weapon/reagent_containers/food/condiment/attack(var/mob/M as mob, var/mob/user as mob, var/def_zone)
if(standard_feed_mob(user, M))
return
/obj/item/weapon/reagent_containers/food/condiment/afterattack(var/obj/target, var/mob/user, var/flag)
if(standard_dispenser_refill(user, target))
return
if(standard_pour_into(user, target))
return
if(istype(target, /obj/item/weapon/reagent_containers/food/snacks)) // These are not opencontainers but we can transfer to them
if(!reagents || !reagents.total_volume)
user << "<span class='notice'>There is no condiment left in \the [src].</span>"
return
if(!target.reagents.get_free_space())
user << "<span class='notice'>You can't add more condiment to \the [target].</span>"
return
var/trans = reagents.trans_to_obj(target, amount_per_transfer_from_this)
user << "<span class='notice'>You add [trans] units of the condiment to \the [target].</span>"
else
..()
/obj/item/weapon/reagent_containers/food/condiment/feed_sound(var/mob/user)
playsound(user.loc, 'sound/items/drink.ogg', rand(10, 50), 1)
/obj/item/weapon/reagent_containers/food/condiment/self_feed_message(var/mob/user)
user << "<span class='notice'>You swallow some of contents of \the [src].</span>"
/obj/item/weapon/reagent_containers/food/condiment/on_reagent_change()
if(reagents.reagent_list.len > 0)
switch(reagents.get_master_reagent_id())
if("ketchup")
name = "Ketchup"
desc = "You feel more American already."
icon_state = "ketchup"
center_of_mass = list("x"=16, "y"=6)
if("capsaicin")
name = "Hotsauce"
desc = "You can almost TASTE the stomach ulcers now!"
icon_state = "hotsauce"
center_of_mass = list("x"=16, "y"=6)
if("enzyme")
name = "Universal Enzyme"
desc = "Used in cooking various dishes."
icon_state = "enzyme"
center_of_mass = list("x"=16, "y"=6)
if("soysauce")
name = "Soy Sauce"
desc = "A salty soy-based flavoring."
icon_state = "soysauce"
center_of_mass = list("x"=16, "y"=6)
if("frostoil")
name = "Coldsauce"
desc = "Leaves the tongue numb in its passage."
icon_state = "coldsauce"
center_of_mass = list("x"=16, "y"=6)
if("sodiumchloride")
name = "Salt Shaker"
desc = "Salt. From space oceans, presumably."
icon_state = "saltshaker"
center_of_mass = list("x"=16, "y"=10)
if("blackpepper")
name = "Pepper Mill"
desc = "Often used to flavor food or make people sneeze."
icon_state = "peppermillsmall"
center_of_mass = list("x"=16, "y"=10)
if("cornoil")
name = "Corn Oil"
desc = "A delicious oil used in cooking. Made from corn."
icon_state = "oliveoil"
center_of_mass = list("x"=16, "y"=6)
if("sugar")
name = "Sugar"
desc = "Tastey space sugar!"
center_of_mass = list("x"=16, "y"=6)
else
name = "Misc Condiment Bottle"
if (reagents.reagent_list.len==1)
desc = "Looks like it is [reagents.get_master_reagent_name()], but you are not sure."
else
desc = "A mixture of various condiments. [reagents.get_master_reagent_name()] is one of them."
icon_state = "mixedcondiments"
center_of_mass = list("x"=16, "y"=6)
else
icon_state = "emptycondiment"
name = "Condiment Bottle"
desc = "An empty condiment bottle."
center_of_mass = list("x"=16, "y"=6)
return
/obj/item/weapon/reagent_containers/food/condiment/enzyme
name = "Universal Enzyme"
desc = "Used in cooking various dishes."
icon_state = "enzyme"
/obj/item/weapon/reagent_containers/food/condiment/enzyme/New()
..()
reagents.add_reagent("enzyme", 50)
/obj/item/weapon/reagent_containers/food/condiment/sugar/New()
..()
reagents.add_reagent("sugar", 50)
/obj/item/weapon/reagent_containers/food/condiment/small
possible_transfer_amounts = list(1,20)
amount_per_transfer_from_this = 1
volume = 20
center_of_mass = list()
/obj/item/weapon/reagent_containers/food/condiment/small/on_reagent_change()
return
/obj/item/weapon/reagent_containers/food/condiment/small/saltshaker //Seperate from above since it's a small shaker rather then
name = "salt shaker" // a large one.
desc = "Salt. From space oceans, presumably."
icon_state = "saltshakersmall"
/obj/item/weapon/reagent_containers/food/condiment/small/saltshaker/New()
..()
reagents.add_reagent("sodiumchloride", 20)
/obj/item/weapon/reagent_containers/food/condiment/small/peppermill
name = "pepper mill"
desc = "Often used to flavor food or make people sneeze."
icon_state = "peppermillsmall"
/obj/item/weapon/reagent_containers/food/condiment/small/peppermill/New()
..()
reagents.add_reagent("blackpepper", 20)
/obj/item/weapon/reagent_containers/food/condiment/small/sugar
name = "sugar"
desc = "Sweetness in a bottle"
icon_state = "sugarsmall"
/obj/item/weapon/reagent_containers/food/condiment/small/sugar/New()
..()
reagents.add_reagent("sugar", 20)
/obj/item/weapon/reagent_containers/food/condiment/flour
name = "flour sack"
desc = "A big bag of flour. Good for baking!"
icon = 'icons/obj/food.dmi'
icon_state = "flour"
/obj/item/weapon/reagent_containers/food/condiment/flour/on_reagent_change()
return
/obj/item/weapon/reagent_containers/food/condiment/flour/New()
..()
reagents.add_reagent("flour", 30)
src.pixel_x = rand(-10.0, 10)
src.pixel_y = rand(-10.0, 10)
@@ -1,313 +1,313 @@
////////////////////////////////////////////////////////////////////////////////
/// Drinks.
////////////////////////////////////////////////////////////////////////////////
/obj/item/weapon/reagent_containers/food/drinks
name = "drink"
desc = "yummy"
icon = 'icons/obj/drinks.dmi'
icon_state = null
flags = OPENCONTAINER
amount_per_transfer_from_this = 5
volume = 50
/obj/item/weapon/reagent_containers/food/drinks/on_reagent_change()
if (reagents.reagent_list.len > 0)
var/datum/reagent/R = reagents.get_master_reagent()
if(R.price_tag)
price_tag = R.price_tag
else
price_tag = null
return
/obj/item/weapon/reagent_containers/food/drinks/attack_self(mob/user as mob)
if(!is_open_container())
open(user)
/obj/item/weapon/reagent_containers/food/drinks/proc/open(mob/user)
playsound(loc,"canopen", rand(10,50), 1)
user << "<span class='notice'>You open [src] with an audible pop!</span>"
flags |= OPENCONTAINER
/obj/item/weapon/reagent_containers/food/drinks/attack(mob/M as mob, mob/user as mob, def_zone)
if(force && !(flags & NOBLUDGEON) && user.a_intent == I_HURT)
return ..()
if(standard_feed_mob(user, M))
return
return 0
/obj/item/weapon/reagent_containers/food/drinks/afterattack(obj/target, mob/user, proximity)
if(!proximity) return
if(standard_dispenser_refill(user, target))
return
if(standard_pour_into(user, target))
return
return ..()
/obj/item/weapon/reagent_containers/food/drinks/standard_feed_mob(var/mob/user, var/mob/target)
if(!is_open_container())
user << "<span class='notice'>You need to open [src]!</span>"
return 1
return ..()
/obj/item/weapon/reagent_containers/food/drinks/standard_dispenser_refill(var/mob/user, var/obj/structure/reagent_dispensers/target)
if(!is_open_container())
user << "<span class='notice'>You need to open [src]!</span>"
return 1
return ..()
/obj/item/weapon/reagent_containers/food/drinks/standard_pour_into(var/mob/user, var/atom/target)
if(!is_open_container())
user << "<span class='notice'>You need to open [src]!</span>"
return 1
return ..()
/obj/item/weapon/reagent_containers/food/drinks/self_feed_message(var/mob/user)
user << "<span class='notice'>You swallow a gulp from \the [src].</span>"
/obj/item/weapon/reagent_containers/food/drinks/feed_sound(var/mob/user)
playsound(user.loc, 'sound/items/drink.ogg', rand(10, 50), 1)
/obj/item/weapon/reagent_containers/food/drinks/examine(mob/user)
if(!..(user, 1))
return
if(!reagents || reagents.total_volume == 0)
user << "<span class='notice'>\The [src] is empty!</span>"
else if (reagents.total_volume <= volume * 0.25)
user << "<span class='notice'>\The [src] is almost empty!</span>"
else if (reagents.total_volume <= volume * 0.66)
user << "<span class='notice'>\The [src] is half full!</span>"
else if (reagents.total_volume <= volume * 0.90)
user << "<span class='notice'>\The [src] is almost full!</span>"
else
user << "<span class='notice'>\The [src] is full!</span>"
////////////////////////////////////////////////////////////////////////////////
/// Drinks. END
////////////////////////////////////////////////////////////////////////////////
/obj/item/weapon/reagent_containers/food/drinks/golden_cup
desc = "A golden cup"
name = "golden cup"
icon_state = "golden_cup"
item_state = "" //nope :(
w_class = ITEMSIZE_LARGE
force = 14
throwforce = 10
amount_per_transfer_from_this = 20
possible_transfer_amounts = null
volume = 150
flags = CONDUCT | OPENCONTAINER
/obj/item/weapon/reagent_containers/food/drinks/golden_cup/on_reagent_change()
..()
///////////////////////////////////////////////Drinks
//Notes by Darem: Drinks are simply containers that start preloaded. Unlike condiments, the contents can be ingested directly
// rather then having to add it to something else first. They should only contain liquids. They have a default container size of 50.
// Formatting is the same as food.
/obj/item/weapon/reagent_containers/food/drinks/milk
name = "milk carton"
desc = "It's milk. White and nutritious goodness!"
icon_state = "milk"
item_state = "carton"
center_of_mass = list("x"=16, "y"=9)
/obj/item/weapon/reagent_containers/food/drinks/milk/New()
..()
reagents.add_reagent("milk", 50)
/obj/item/weapon/reagent_containers/food/drinks/soymilk
name = "soymilk carton"
desc = "It's soy milk. White and nutritious goodness!"
icon_state = "soymilk"
item_state = "carton"
center_of_mass = list("x"=16, "y"=9)
/obj/item/weapon/reagent_containers/food/drinks/soymilk/New()
..()
reagents.add_reagent("soymilk", 50)
/obj/item/weapon/reagent_containers/food/drinks/smallmilk
name = "small milk carton"
desc = "It's milk. White and nutritious goodness!"
volume = 30
icon_state = "mini-milk"
item_state = "carton"
center_of_mass = list("x"=16, "y"=9)
/obj/item/weapon/reagent_containers/food/drinks/smallmilk/New()
..()
reagents.add_reagent("milk", 30)
/obj/item/weapon/reagent_containers/food/drinks/smallchocmilk
name = "small chocolate milk carton"
desc = "It's milk! This one is in delicious chocolate flavour."
volume = 30
icon_state = "mini-milk_choco"
item_state = "carton"
center_of_mass = list("x"=16, "y"=9)
/obj/item/weapon/reagent_containers/food/drinks/smallchocmilk/New()
..()
reagents.add_reagent("chocolate_milk", 30)
/obj/item/weapon/reagent_containers/food/drinks/coffee
name = "\improper Robust Coffee"
desc = "Careful, the beverage you're about to enjoy is extremely hot."
icon_state = "coffee"
center_of_mass = list("x"=15, "y"=10)
/obj/item/weapon/reagent_containers/food/drinks/coffee/New()
..()
reagents.add_reagent("coffee", 30)
/obj/item/weapon/reagent_containers/food/drinks/tea
name = "cup of Duke Purple Tea"
desc = "An insult to Duke Purple is an insult to the Space Queen! Any proper gentleman will fight you, if you sully this tea."
icon_state = "teacup"
item_state = "coffee"
center_of_mass = list("x"=16, "y"=14)
/obj/item/weapon/reagent_containers/food/drinks/tea/New()
..()
reagents.add_reagent("tea", 30)
/obj/item/weapon/reagent_containers/food/drinks/ice
name = "cup of ice"
desc = "Careful, cold ice, do not chew."
icon_state = "coffee"
center_of_mass = list("x"=15, "y"=10)
/obj/item/weapon/reagent_containers/food/drinks/ice/New()
..()
reagents.add_reagent("ice", 30)
/obj/item/weapon/reagent_containers/food/drinks/h_chocolate
name = "cup of Dutch hot coco"
desc = "Made in Space South America."
icon_state = "hot_coco"
item_state = "coffee"
center_of_mass = list("x"=15, "y"=13)
/obj/item/weapon/reagent_containers/food/drinks/h_chocolate/New()
..()
reagents.add_reagent("hot_coco", 30)
/obj/item/weapon/reagent_containers/food/drinks/dry_ramen
name = "Cup Ramen"
desc = "Just add 10ml water, self heats! A taste that reminds you of your school years."
icon_state = "ramen"
center_of_mass = list("x"=16, "y"=11)
/obj/item/weapon/reagent_containers/food/drinks/dry_ramen/New()
..()
reagents.add_reagent("dry_ramen", 30)
/obj/item/weapon/reagent_containers/food/drinks/sillycup
name = "paper cup"
desc = "A paper water cup."
icon_state = "water_cup_e"
possible_transfer_amounts = null
volume = 10
center_of_mass = list("x"=16, "y"=12)
/obj/item/weapon/reagent_containers/food/drinks/sillycup/New()
..()
/obj/item/weapon/reagent_containers/food/drinks/sillycup/on_reagent_change()
..()
if(reagents.total_volume)
icon_state = "water_cup"
else
icon_state = "water_cup_e"
/obj/item/weapon/reagent_containers/food/drinks/sillycup/MouseDrop(obj/over_object as obj)
if(!reagents.total_volume && istype(over_object, /obj/structure/reagent_dispensers/water_cooler))
if(over_object.Adjacent(usr))
var/obj/structure/reagent_dispensers/water_cooler/W = over_object
if(W.cupholder && W.cups < 10)
W.cups++
usr << "<span class='notice'>You put the [src] in the cup dispenser.</span>"
qdel(src)
W.update_icon()
else
return ..()
//////////////////////////drinkingglass and shaker//
//Note by Darem: This code handles the mixing of drinks. New drinks go in three places: In Chemistry-Reagents.dm (for the drink
// itself), in Chemistry-Recipes.dm (for the reaction that changes the components into the drink), and here (for the drinking glass
// icon states.
/obj/item/weapon/reagent_containers/food/drinks/shaker
name = "shaker"
desc = "A metal shaker to mix drinks in."
icon_state = "shaker"
amount_per_transfer_from_this = 10
volume = 120
center_of_mass = list("x"=17, "y"=10)
/obj/item/weapon/reagent_containers/food/drinks/shaker/on_reagent_change()
..()
/obj/item/weapon/reagent_containers/food/drinks/teapot
name = "teapot"
desc = "An elegant teapot. It simply oozes class."
icon_state = "teapot"
item_state = "teapot"
amount_per_transfer_from_this = 10
volume = 120
center_of_mass = list("x"=17, "y"=7)
/obj/item/weapon/reagent_containers/food/drinks/teapot/on_reagent_change()
..()
/obj/item/weapon/reagent_containers/food/drinks/flask
name = "\improper Colony Director's flask"
desc = "A metal flask belonging to the Colony Director"
icon_state = "flask"
volume = 60
center_of_mass = list("x"=17, "y"=7)
/obj/item/weapon/reagent_containers/food/drinks/flask/on_reagent_change()
..()
/obj/item/weapon/reagent_containers/food/drinks/flask/shiny
name = "shiny flask"
desc = "A shiny metal flask. It appears to have a Greek symbol inscribed on it."
icon_state = "shinyflask"
/obj/item/weapon/reagent_containers/food/drinks/flask/lithium
name = "lithium flask"
desc = "A flask with a Lithium Atom symbol on it."
icon_state = "lithiumflask"
/obj/item/weapon/reagent_containers/food/drinks/flask/detflask
name = "\improper Detective's flask"
desc = "A metal flask with a leather band and golden badge belonging to the detective."
icon_state = "detflask"
volume = 60
center_of_mass = list("x"=17, "y"=8)
/obj/item/weapon/reagent_containers/food/drinks/flask/barflask
name = "flask"
desc = "For those who can't be bothered to hang out at the bar to drink."
icon_state = "barflask"
volume = 60
center_of_mass = list("x"=17, "y"=7)
/obj/item/weapon/reagent_containers/food/drinks/flask/vacuumflask
name = "vacuum flask"
desc = "Keeping your drinks at the perfect temperature since 1892."
icon_state = "vacuumflask"
volume = 60
center_of_mass = list("x"=15, "y"=4)
/obj/item/weapon/reagent_containers/food/drinks/britcup
name = "cup"
desc = "A cup with the British flag emblazoned on it."
icon_state = "britcup"
volume = 30
center_of_mass = list("x"=15, "y"=13)
/obj/item/weapon/reagent_containers/food/drinks/britcup/on_reagent_change()
..()
////////////////////////////////////////////////////////////////////////////////
/// Drinks.
////////////////////////////////////////////////////////////////////////////////
/obj/item/weapon/reagent_containers/food/drinks
name = "drink"
desc = "yummy"
icon = 'icons/obj/drinks.dmi'
icon_state = null
flags = OPENCONTAINER
amount_per_transfer_from_this = 5
volume = 50
/obj/item/weapon/reagent_containers/food/drinks/on_reagent_change()
if (reagents.reagent_list.len > 0)
var/datum/reagent/R = reagents.get_master_reagent()
if(R.price_tag)
price_tag = R.price_tag
else
price_tag = null
return
/obj/item/weapon/reagent_containers/food/drinks/attack_self(mob/user as mob)
if(!is_open_container())
open(user)
/obj/item/weapon/reagent_containers/food/drinks/proc/open(mob/user)
playsound(loc,"canopen", rand(10,50), 1)
user << "<span class='notice'>You open [src] with an audible pop!</span>"
flags |= OPENCONTAINER
/obj/item/weapon/reagent_containers/food/drinks/attack(mob/M as mob, mob/user as mob, def_zone)
if(force && !(flags & NOBLUDGEON) && user.a_intent == I_HURT)
return ..()
if(standard_feed_mob(user, M))
return
return 0
/obj/item/weapon/reagent_containers/food/drinks/afterattack(obj/target, mob/user, proximity)
if(!proximity) return
if(standard_dispenser_refill(user, target))
return
if(standard_pour_into(user, target))
return
return ..()
/obj/item/weapon/reagent_containers/food/drinks/standard_feed_mob(var/mob/user, var/mob/target)
if(!is_open_container())
user << "<span class='notice'>You need to open [src]!</span>"
return 1
return ..()
/obj/item/weapon/reagent_containers/food/drinks/standard_dispenser_refill(var/mob/user, var/obj/structure/reagent_dispensers/target)
if(!is_open_container())
user << "<span class='notice'>You need to open [src]!</span>"
return 1
return ..()
/obj/item/weapon/reagent_containers/food/drinks/standard_pour_into(var/mob/user, var/atom/target)
if(!is_open_container())
user << "<span class='notice'>You need to open [src]!</span>"
return 1
return ..()
/obj/item/weapon/reagent_containers/food/drinks/self_feed_message(var/mob/user)
user << "<span class='notice'>You swallow a gulp from \the [src].</span>"
/obj/item/weapon/reagent_containers/food/drinks/feed_sound(var/mob/user)
playsound(user.loc, 'sound/items/drink.ogg', rand(10, 50), 1)
/obj/item/weapon/reagent_containers/food/drinks/examine(mob/user)
if(!..(user, 1))
return
if(!reagents || reagents.total_volume == 0)
user << "<span class='notice'>\The [src] is empty!</span>"
else if (reagents.total_volume <= volume * 0.25)
user << "<span class='notice'>\The [src] is almost empty!</span>"
else if (reagents.total_volume <= volume * 0.66)
user << "<span class='notice'>\The [src] is half full!</span>"
else if (reagents.total_volume <= volume * 0.90)
user << "<span class='notice'>\The [src] is almost full!</span>"
else
user << "<span class='notice'>\The [src] is full!</span>"
////////////////////////////////////////////////////////////////////////////////
/// Drinks. END
////////////////////////////////////////////////////////////////////////////////
/obj/item/weapon/reagent_containers/food/drinks/golden_cup
desc = "A golden cup"
name = "golden cup"
icon_state = "golden_cup"
item_state = "" //nope :(
w_class = ITEMSIZE_LARGE
force = 14
throwforce = 10
amount_per_transfer_from_this = 20
possible_transfer_amounts = null
volume = 150
flags = CONDUCT | OPENCONTAINER
/obj/item/weapon/reagent_containers/food/drinks/golden_cup/on_reagent_change()
..()
///////////////////////////////////////////////Drinks
//Notes by Darem: Drinks are simply containers that start preloaded. Unlike condiments, the contents can be ingested directly
// rather then having to add it to something else first. They should only contain liquids. They have a default container size of 50.
// Formatting is the same as food.
/obj/item/weapon/reagent_containers/food/drinks/milk
name = "milk carton"
desc = "It's milk. White and nutritious goodness!"
icon_state = "milk"
item_state = "carton"
center_of_mass = list("x"=16, "y"=9)
/obj/item/weapon/reagent_containers/food/drinks/milk/New()
..()
reagents.add_reagent("milk", 50)
/obj/item/weapon/reagent_containers/food/drinks/soymilk
name = "soymilk carton"
desc = "It's soy milk. White and nutritious goodness!"
icon_state = "soymilk"
item_state = "carton"
center_of_mass = list("x"=16, "y"=9)
/obj/item/weapon/reagent_containers/food/drinks/soymilk/New()
..()
reagents.add_reagent("soymilk", 50)
/obj/item/weapon/reagent_containers/food/drinks/smallmilk
name = "small milk carton"
desc = "It's milk. White and nutritious goodness!"
volume = 30
icon_state = "mini-milk"
item_state = "carton"
center_of_mass = list("x"=16, "y"=9)
/obj/item/weapon/reagent_containers/food/drinks/smallmilk/New()
..()
reagents.add_reagent("milk", 30)
/obj/item/weapon/reagent_containers/food/drinks/smallchocmilk
name = "small chocolate milk carton"
desc = "It's milk! This one is in delicious chocolate flavour."
volume = 30
icon_state = "mini-milk_choco"
item_state = "carton"
center_of_mass = list("x"=16, "y"=9)
/obj/item/weapon/reagent_containers/food/drinks/smallchocmilk/New()
..()
reagents.add_reagent("chocolate_milk", 30)
/obj/item/weapon/reagent_containers/food/drinks/coffee
name = "\improper Robust Coffee"
desc = "Careful, the beverage you're about to enjoy is extremely hot."
icon_state = "coffee"
center_of_mass = list("x"=15, "y"=10)
/obj/item/weapon/reagent_containers/food/drinks/coffee/New()
..()
reagents.add_reagent("coffee", 30)
/obj/item/weapon/reagent_containers/food/drinks/tea
name = "cup of Duke Purple Tea"
desc = "An insult to Duke Purple is an insult to the Space Queen! Any proper gentleman will fight you, if you sully this tea."
icon_state = "teacup"
item_state = "coffee"
center_of_mass = list("x"=16, "y"=14)
/obj/item/weapon/reagent_containers/food/drinks/tea/New()
..()
reagents.add_reagent("tea", 30)
/obj/item/weapon/reagent_containers/food/drinks/ice
name = "cup of ice"
desc = "Careful, cold ice, do not chew."
icon_state = "coffee"
center_of_mass = list("x"=15, "y"=10)
/obj/item/weapon/reagent_containers/food/drinks/ice/New()
..()
reagents.add_reagent("ice", 30)
/obj/item/weapon/reagent_containers/food/drinks/h_chocolate
name = "cup of Dutch hot coco"
desc = "Made in Space South America."
icon_state = "hot_coco"
item_state = "coffee"
center_of_mass = list("x"=15, "y"=13)
/obj/item/weapon/reagent_containers/food/drinks/h_chocolate/New()
..()
reagents.add_reagent("hot_coco", 30)
/obj/item/weapon/reagent_containers/food/drinks/dry_ramen
name = "Cup Ramen"
desc = "Just add 10ml water, self heats! A taste that reminds you of your school years."
icon_state = "ramen"
center_of_mass = list("x"=16, "y"=11)
/obj/item/weapon/reagent_containers/food/drinks/dry_ramen/New()
..()
reagents.add_reagent("dry_ramen", 30)
/obj/item/weapon/reagent_containers/food/drinks/sillycup
name = "paper cup"
desc = "A paper water cup."
icon_state = "water_cup_e"
possible_transfer_amounts = null
volume = 10
center_of_mass = list("x"=16, "y"=12)
/obj/item/weapon/reagent_containers/food/drinks/sillycup/New()
..()
/obj/item/weapon/reagent_containers/food/drinks/sillycup/on_reagent_change()
..()
if(reagents.total_volume)
icon_state = "water_cup"
else
icon_state = "water_cup_e"
/obj/item/weapon/reagent_containers/food/drinks/sillycup/MouseDrop(obj/over_object as obj)
if(!reagents.total_volume && istype(over_object, /obj/structure/reagent_dispensers/water_cooler))
if(over_object.Adjacent(usr))
var/obj/structure/reagent_dispensers/water_cooler/W = over_object
if(W.cupholder && W.cups < 10)
W.cups++
usr << "<span class='notice'>You put the [src] in the cup dispenser.</span>"
qdel(src)
W.update_icon()
else
return ..()
//////////////////////////drinkingglass and shaker//
//Note by Darem: This code handles the mixing of drinks. New drinks go in three places: In Chemistry-Reagents.dm (for the drink
// itself), in Chemistry-Recipes.dm (for the reaction that changes the components into the drink), and here (for the drinking glass
// icon states.
/obj/item/weapon/reagent_containers/food/drinks/shaker
name = "shaker"
desc = "A metal shaker to mix drinks in."
icon_state = "shaker"
amount_per_transfer_from_this = 10
volume = 120
center_of_mass = list("x"=17, "y"=10)
/obj/item/weapon/reagent_containers/food/drinks/shaker/on_reagent_change()
..()
/obj/item/weapon/reagent_containers/food/drinks/teapot
name = "teapot"
desc = "An elegant teapot. It simply oozes class."
icon_state = "teapot"
item_state = "teapot"
amount_per_transfer_from_this = 10
volume = 120
center_of_mass = list("x"=17, "y"=7)
/obj/item/weapon/reagent_containers/food/drinks/teapot/on_reagent_change()
..()
/obj/item/weapon/reagent_containers/food/drinks/flask
name = "\improper Colony Director's flask"
desc = "A metal flask belonging to the Colony Director"
icon_state = "flask"
volume = 60
center_of_mass = list("x"=17, "y"=7)
/obj/item/weapon/reagent_containers/food/drinks/flask/on_reagent_change()
..()
/obj/item/weapon/reagent_containers/food/drinks/flask/shiny
name = "shiny flask"
desc = "A shiny metal flask. It appears to have a Greek symbol inscribed on it."
icon_state = "shinyflask"
/obj/item/weapon/reagent_containers/food/drinks/flask/lithium
name = "lithium flask"
desc = "A flask with a Lithium Atom symbol on it."
icon_state = "lithiumflask"
/obj/item/weapon/reagent_containers/food/drinks/flask/detflask
name = "\improper Detective's flask"
desc = "A metal flask with a leather band and golden badge belonging to the detective."
icon_state = "detflask"
volume = 60
center_of_mass = list("x"=17, "y"=8)
/obj/item/weapon/reagent_containers/food/drinks/flask/barflask
name = "flask"
desc = "For those who can't be bothered to hang out at the bar to drink."
icon_state = "barflask"
volume = 60
center_of_mass = list("x"=17, "y"=7)
/obj/item/weapon/reagent_containers/food/drinks/flask/vacuumflask
name = "vacuum flask"
desc = "Keeping your drinks at the perfect temperature since 1892."
icon_state = "vacuumflask"
volume = 60
center_of_mass = list("x"=15, "y"=4)
/obj/item/weapon/reagent_containers/food/drinks/britcup
name = "cup"
desc = "A cup with the British flag emblazoned on it."
icon_state = "britcup"
volume = 30
center_of_mass = list("x"=15, "y"=13)
/obj/item/weapon/reagent_containers/food/drinks/britcup/on_reagent_change()
..()
@@ -1,178 +1,178 @@
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass
name = "glass"
desc = "Your standard drinking glass."
icon_state = "glass_empty"
amount_per_transfer_from_this = 5
volume = 30
unacidable = 1 //glass
center_of_mass = list("x"=16, "y"=10)
matter = list("glass" = 500)
on_reagent_change()
/*if(reagents.reagent_list.len > 1 )
icon_state = "glass_brown"
name = "Glass of Hooch"
desc = "Two or more drinks, mixed together."*/
/*else if(reagents.reagent_list.len == 1)
for(var/datum/reagent/R in reagents.reagent_list)
switch(R.id)*/
if (reagents.reagent_list.len > 0)
var/datum/reagent/R = reagents.get_master_reagent()
if(R.glass_icon_state)
icon_state = R.glass_icon_state
else
icon_state = "glass_brown"
if(R.glass_name)
name = R.glass_name
else
name = "Glass of.. what?"
if(R.glass_desc)
desc = R.glass_desc
else
desc = "You can't really tell what this is."
if(R.glass_center_of_mass)
center_of_mass = R.glass_center_of_mass
else
center_of_mass = list("x"=16, "y"=10)
if(R.price_tag)
price_tag = R.price_tag
else
price_tag = null
else
icon_state = "glass_empty"
name = "glass"
desc = "Your standard drinking glass."
center_of_mass = list("x"=16, "y"=10)
return
/obj/item/weapon/reagent_containers/food/drinks/cup
name = "coffee cup"
desc = "The container of oriental luxuries."
icon_state = "cup_empty"
amount_per_transfer_from_this = 5
volume = 30
center_of_mass = list("x"=16, "y"=16)
on_reagent_change()
if (reagents.reagent_list.len > 0)
var/datum/reagent/R = reagents.get_master_reagent()
if(R.cup_icon_state)
icon_state = R.cup_icon_state
else
icon_state = "cup_brown"
if(R.cup_name)
name = R.cup_name
else
name = "Cup of.. what?"
if(R.cup_desc)
desc = R.cup_desc
else
desc = "You can't really tell what this is."
if(R.cup_center_of_mass)
center_of_mass = R.cup_center_of_mass
else
center_of_mass = list("x"=16, "y"=16)
if(R.price_tag)
price_tag = R.price_tag
else
price_tag = null
else
icon_state = "cup_empty"
name = "coffee cup"
desc = "The container of oriental luxuries."
center_of_mass = list("x"=16, "y"=16)
return
// for /obj/machinery/vending/sovietsoda
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/soda
New()
..()
reagents.add_reagent("sodawater", 50)
on_reagent_change()
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/cola
New()
..()
reagents.add_reagent("cola", 50)
on_reagent_change()
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/shotglass
name = "shot glass"
desc = "No glasses were shot in the making of this glass."
icon_state = "shotglass"
amount_per_transfer_from_this = 10
volume = 10
matter = list("glass" = 175)
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/shotglass/on_reagent_change()
overlays.Cut()
if(reagents.total_volume)
var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]1")
switch(reagents.total_volume)
if(0 to 3) filling.icon_state = "[icon_state]1"
if(4 to 7) filling.icon_state = "[icon_state]5"
if(8 to INFINITY) filling.icon_state = "[icon_state]12"
filling.color += reagents.get_color()
overlays += filling
name = "shot glass of " + reagents.get_master_reagent_name() //No matter what, the glass will tell you the reagent's name. Might be too abusable in the future.
else
name = "shot glass"
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/fitnessflask
name = "fitness shaker"
desc = "Big enough to contain enough protein to get perfectly swole. Don't mind the bits."
icon_state = "fitness-cup_black"
volume = 100
matter = list("plastic" = 2000)
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/fitnessflask/New()
..()
icon_state = pick("fitness-cup_black", "fitness-cup_red", "fitness-cup_black")
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/fitnessflask/on_reagent_change()
overlays.Cut()
if(reagents.total_volume)
var/image/filling = image('icons/obj/reagentfillings.dmi', src, "fitness-cup10")
switch(reagents.total_volume)
if(0 to 10) filling.icon_state = "fitness-cup10"
if(11 to 20) filling.icon_state = "fitness-cup20"
if(21 to 29) filling.icon_state = "fitness-cup30"
if(30 to 39) filling.icon_state = "fitness-cup40"
if(40 to 49) filling.icon_state = "fitness-cup50"
if(50 to 59) filling.icon_state = "fitness-cup60"
if(60 to 69) filling.icon_state = "fitness-cup70"
if(70 to 79) filling.icon_state = "fitness-cup80"
if(80 to 89) filling.icon_state = "fitness-cup90"
if(90 to INFINITY) filling.icon_state = "fitness-cup100"
filling.color += reagents.get_color()
overlays += filling
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/fitnessflask/proteinshake
name = "protein shake"
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/fitnessflask/proteinshake/New()
..()
reagents.add_reagent("nutriment", 30)
reagents.add_reagent("iron", 10)
reagents.add_reagent("protein", 15)
reagents.add_reagent("water", 45)
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass
name = "glass"
desc = "Your standard drinking glass."
icon_state = "glass_empty"
amount_per_transfer_from_this = 5
volume = 30
unacidable = 1 //glass
center_of_mass = list("x"=16, "y"=10)
matter = list("glass" = 500)
on_reagent_change()
/*if(reagents.reagent_list.len > 1 )
icon_state = "glass_brown"
name = "Glass of Hooch"
desc = "Two or more drinks, mixed together."*/
/*else if(reagents.reagent_list.len == 1)
for(var/datum/reagent/R in reagents.reagent_list)
switch(R.id)*/
if (reagents.reagent_list.len > 0)
var/datum/reagent/R = reagents.get_master_reagent()
if(R.glass_icon_state)
icon_state = R.glass_icon_state
else
icon_state = "glass_brown"
if(R.glass_name)
name = R.glass_name
else
name = "Glass of.. what?"
if(R.glass_desc)
desc = R.glass_desc
else
desc = "You can't really tell what this is."
if(R.glass_center_of_mass)
center_of_mass = R.glass_center_of_mass
else
center_of_mass = list("x"=16, "y"=10)
if(R.price_tag)
price_tag = R.price_tag
else
price_tag = null
else
icon_state = "glass_empty"
name = "glass"
desc = "Your standard drinking glass."
center_of_mass = list("x"=16, "y"=10)
return
/obj/item/weapon/reagent_containers/food/drinks/cup
name = "coffee cup"
desc = "The container of oriental luxuries."
icon_state = "cup_empty"
amount_per_transfer_from_this = 5
volume = 30
center_of_mass = list("x"=16, "y"=16)
on_reagent_change()
if (reagents.reagent_list.len > 0)
var/datum/reagent/R = reagents.get_master_reagent()
if(R.cup_icon_state)
icon_state = R.cup_icon_state
else
icon_state = "cup_brown"
if(R.cup_name)
name = R.cup_name
else
name = "Cup of.. what?"
if(R.cup_desc)
desc = R.cup_desc
else
desc = "You can't really tell what this is."
if(R.cup_center_of_mass)
center_of_mass = R.cup_center_of_mass
else
center_of_mass = list("x"=16, "y"=16)
if(R.price_tag)
price_tag = R.price_tag
else
price_tag = null
else
icon_state = "cup_empty"
name = "coffee cup"
desc = "The container of oriental luxuries."
center_of_mass = list("x"=16, "y"=16)
return
// for /obj/machinery/vending/sovietsoda
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/soda
New()
..()
reagents.add_reagent("sodawater", 50)
on_reagent_change()
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/cola
New()
..()
reagents.add_reagent("cola", 50)
on_reagent_change()
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/shotglass
name = "shot glass"
desc = "No glasses were shot in the making of this glass."
icon_state = "shotglass"
amount_per_transfer_from_this = 10
volume = 10
matter = list("glass" = 175)
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/shotglass/on_reagent_change()
overlays.Cut()
if(reagents.total_volume)
var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]1")
switch(reagents.total_volume)
if(0 to 3) filling.icon_state = "[icon_state]1"
if(4 to 7) filling.icon_state = "[icon_state]5"
if(8 to INFINITY) filling.icon_state = "[icon_state]12"
filling.color += reagents.get_color()
overlays += filling
name = "shot glass of " + reagents.get_master_reagent_name() //No matter what, the glass will tell you the reagent's name. Might be too abusable in the future.
else
name = "shot glass"
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/fitnessflask
name = "fitness shaker"
desc = "Big enough to contain enough protein to get perfectly swole. Don't mind the bits."
icon_state = "fitness-cup_black"
volume = 100
matter = list("plastic" = 2000)
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/fitnessflask/New()
..()
icon_state = pick("fitness-cup_black", "fitness-cup_red", "fitness-cup_black")
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/fitnessflask/on_reagent_change()
overlays.Cut()
if(reagents.total_volume)
var/image/filling = image('icons/obj/reagentfillings.dmi', src, "fitness-cup10")
switch(reagents.total_volume)
if(0 to 10) filling.icon_state = "fitness-cup10"
if(11 to 20) filling.icon_state = "fitness-cup20"
if(21 to 29) filling.icon_state = "fitness-cup30"
if(30 to 39) filling.icon_state = "fitness-cup40"
if(40 to 49) filling.icon_state = "fitness-cup50"
if(50 to 59) filling.icon_state = "fitness-cup60"
if(60 to 69) filling.icon_state = "fitness-cup70"
if(70 to 79) filling.icon_state = "fitness-cup80"
if(80 to 89) filling.icon_state = "fitness-cup90"
if(90 to INFINITY) filling.icon_state = "fitness-cup100"
filling.color += reagents.get_color()
overlays += filling
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/fitnessflask/proteinshake
name = "protein shake"
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/fitnessflask/proteinshake/New()
..()
reagents.add_reagent("nutriment", 30)
reagents.add_reagent("iron", 10)
reagents.add_reagent("protein", 15)
reagents.add_reagent("water", 45)
on_reagent_change()
@@ -1,25 +1,25 @@
///jar
/obj/item/weapon/reagent_containers/food/drinks/jar
name = "empty jar"
desc = "A jar. You're not sure what it's supposed to hold."
icon_state = "jar"
item_state = "beaker"
center_of_mass = list("x"=15, "y"=8)
unacidable = 1
/obj/item/weapon/reagent_containers/food/drinks/jar/on_reagent_change()
if (reagents.reagent_list.len > 0)
switch(reagents.get_master_reagent_id())
if("slime")
icon_state = "jar_slime"
name = "slime jam"
desc = "A jar of slime jam. Delicious!"
else
icon_state ="jar_what"
name = "jar of something"
desc = "You can't really tell what this is."
else
icon_state = "jar"
name = "empty jar"
desc = "A jar. You're not sure what it's supposed to hold."
return
///jar
/obj/item/weapon/reagent_containers/food/drinks/jar
name = "empty jar"
desc = "A jar. You're not sure what it's supposed to hold."
icon_state = "jar"
item_state = "beaker"
center_of_mass = list("x"=15, "y"=8)
unacidable = 1
/obj/item/weapon/reagent_containers/food/drinks/jar/on_reagent_change()
if (reagents.reagent_list.len > 0)
switch(reagents.get_master_reagent_id())
if("slime")
icon_state = "jar_slime"
name = "slime jam"
desc = "A jar of slime jam. Delicious!"
else
icon_state ="jar_what"
name = "jar of something"
desc = "You can't really tell what this is."
else
icon_state = "jar"
name = "empty jar"
desc = "A jar. You're not sure what it's supposed to hold."
return
@@ -1,37 +1,37 @@
/obj/item/weapon/reagent_containers/food/snacks/meat
name = "meat"
desc = "A slab of meat."
icon_state = "meat"
health = 180
filling_color = "#FF1C1C"
center_of_mass = list("x"=16, "y"=14)
/obj/item/weapon/reagent_containers/food/snacks/meat/New()
..()
reagents.add_reagent("protein", 9)
src.bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/meat/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/material/knife))
new /obj/item/weapon/reagent_containers/food/snacks/rawcutlet(src)
new /obj/item/weapon/reagent_containers/food/snacks/rawcutlet(src)
new /obj/item/weapon/reagent_containers/food/snacks/rawcutlet(src)
user << "You cut the meat into thin strips."
qdel(src)
else
..()
/obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh
name = "synthetic meat"
desc = "A synthetic slab of flesh."
// Seperate definitions because some food likes to know if it's human.
// TODO: rewrite kitchen code to check a var on the meat item so we can remove
// all these sybtypes.
/obj/item/weapon/reagent_containers/food/snacks/meat/human
/obj/item/weapon/reagent_containers/food/snacks/meat/monkey
//same as plain meat
/obj/item/weapon/reagent_containers/food/snacks/meat/corgi
name = "Corgi meat"
/obj/item/weapon/reagent_containers/food/snacks/meat
name = "meat"
desc = "A slab of meat."
icon_state = "meat"
health = 180
filling_color = "#FF1C1C"
center_of_mass = list("x"=16, "y"=14)
/obj/item/weapon/reagent_containers/food/snacks/meat/New()
..()
reagents.add_reagent("protein", 9)
src.bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/meat/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/material/knife))
new /obj/item/weapon/reagent_containers/food/snacks/rawcutlet(src)
new /obj/item/weapon/reagent_containers/food/snacks/rawcutlet(src)
new /obj/item/weapon/reagent_containers/food/snacks/rawcutlet(src)
user << "You cut the meat into thin strips."
qdel(src)
else
..()
/obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh
name = "synthetic meat"
desc = "A synthetic slab of flesh."
// Seperate definitions because some food likes to know if it's human.
// TODO: rewrite kitchen code to check a var on the meat item so we can remove
// all these sybtypes.
/obj/item/weapon/reagent_containers/food/snacks/meat/human
/obj/item/weapon/reagent_containers/food/snacks/meat/monkey
//same as plain meat
/obj/item/weapon/reagent_containers/food/snacks/meat/corgi
name = "Corgi meat"
desc = "Tastes like... well, you know."
@@ -1,175 +1,175 @@
//Not to be confused with /obj/item/weapon/reagent_containers/food/drinks/bottle
/obj/item/weapon/reagent_containers/glass/bottle
name = "bottle"
desc = "A small bottle."
icon = 'icons/obj/chemical.dmi'
icon_state = null
item_state = "atoxinbottle"
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,25,30,60)
flags = 0
volume = 60
/obj/item/weapon/reagent_containers/glass/bottle/on_reagent_change()
update_icon()
/obj/item/weapon/reagent_containers/glass/bottle/pickup(mob/user)
..()
update_icon()
/obj/item/weapon/reagent_containers/glass/bottle/dropped(mob/user)
..()
update_icon()
/obj/item/weapon/reagent_containers/glass/bottle/attack_hand()
..()
update_icon()
/obj/item/weapon/reagent_containers/glass/bottle/New()
..()
if(!icon_state)
icon_state = "bottle-[rand(1,4)]"
/obj/item/weapon/reagent_containers/glass/bottle/update_icon()
overlays.Cut()
if(reagents.total_volume && (icon_state == "bottle-1" || icon_state == "bottle-2" || icon_state == "bottle-3" || icon_state == "bottle-4"))
var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]10")
var/percent = round((reagents.total_volume / volume) * 100)
switch(percent)
if(0 to 9) filling.icon_state = "[icon_state]--10"
if(10 to 24) filling.icon_state = "[icon_state]-10"
if(25 to 49) filling.icon_state = "[icon_state]-25"
if(50 to 74) filling.icon_state = "[icon_state]-50"
if(75 to 79) filling.icon_state = "[icon_state]-75"
if(80 to 90) filling.icon_state = "[icon_state]-80"
if(91 to INFINITY) filling.icon_state = "[icon_state]-100"
filling.color = reagents.get_color()
overlays += filling
if (!is_open_container())
var/image/lid = image(icon, src, "lid_bottle")
overlays += lid
/obj/item/weapon/reagent_containers/glass/bottle/inaprovaline
name = "inaprovaline bottle"
desc = "A small bottle. Contains inaprovaline - used to stabilize patients."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("inaprovaline" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/toxin
name = "toxin bottle"
desc = "A small bottle of toxins. Do not drink, it is poisonous."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-3"
prefill = list("toxin" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/cyanide
name = "cyanide bottle"
desc = "A small bottle of cyanide. Bitter almonds?"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-3"
prefill = list("cyanide" = 30) //volume changed to match chloral
/obj/item/weapon/reagent_containers/glass/bottle/stoxin
name = "soporific bottle"
desc = "A small bottle of soporific. Just the fumes make you sleepy."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-3"
prefill = list("stoxin" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/chloralhydrate
name = "chloral hydrate bottle"
desc = "A small bottle of Choral Hydrate. Mickey's Favorite!"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-3"
prefill = list("chloralhydrate" = 30) //Intentionally low since it is so strong. Still enough to knock someone out.
/obj/item/weapon/reagent_containers/glass/bottle/antitoxin
name = "dylovene bottle"
desc = "A small bottle of dylovene. Counters poisons, and repairs damage. A wonder drug."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("anti_toxin" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/mutagen
name = "unstable mutagen bottle"
desc = "A small bottle of unstable mutagen. Randomly changes the DNA structure of whoever comes in contact."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-1"
prefill = list("mutagen" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/ammonia
name = "ammonia bottle"
desc = "A small bottle."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-1"
prefill = list("ammonia" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/eznutrient
name = "\improper EZ NUtrient bottle"
desc = "A small bottle."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("eznutrient" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/left4zed
name = "\improper Left-4-Zed bottle"
desc = "A small bottle."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("left4zed" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/robustharvest
name = "\improper Robust Harvest"
desc = "A small bottle."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("robustharvest" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/diethylamine
name = "diethylamine bottle"
desc = "A small bottle."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("diethylamine" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/pacid
name = "polytrinic acid bottle"
desc = "A small bottle. Contains a small amount of Polytrinic Acid"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("pacid" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/adminordrazine
name = "adminordrazine bottle"
desc = "A small bottle. Contains the liquid essence of the gods."
icon = 'icons/obj/drinks.dmi'
icon_state = "holyflask"
prefill = list("adminordrazine" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/capsaicin
name = "capsaicin bottle"
desc = "A small bottle. Contains hot sauce."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("capsaicin" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/frostoil
name = "frost oil bottle"
desc = "A small bottle. Contains cold sauce."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("frostoil" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/biomass
name = "biomass bottle"
desc = "A bottle of raw biomass! Gross!"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-3"
//Not to be confused with /obj/item/weapon/reagent_containers/food/drinks/bottle
/obj/item/weapon/reagent_containers/glass/bottle
name = "bottle"
desc = "A small bottle."
icon = 'icons/obj/chemical.dmi'
icon_state = null
item_state = "atoxinbottle"
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,25,30,60)
flags = 0
volume = 60
/obj/item/weapon/reagent_containers/glass/bottle/on_reagent_change()
update_icon()
/obj/item/weapon/reagent_containers/glass/bottle/pickup(mob/user)
..()
update_icon()
/obj/item/weapon/reagent_containers/glass/bottle/dropped(mob/user)
..()
update_icon()
/obj/item/weapon/reagent_containers/glass/bottle/attack_hand()
..()
update_icon()
/obj/item/weapon/reagent_containers/glass/bottle/New()
..()
if(!icon_state)
icon_state = "bottle-[rand(1,4)]"
/obj/item/weapon/reagent_containers/glass/bottle/update_icon()
overlays.Cut()
if(reagents.total_volume && (icon_state == "bottle-1" || icon_state == "bottle-2" || icon_state == "bottle-3" || icon_state == "bottle-4"))
var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]10")
var/percent = round((reagents.total_volume / volume) * 100)
switch(percent)
if(0 to 9) filling.icon_state = "[icon_state]--10"
if(10 to 24) filling.icon_state = "[icon_state]-10"
if(25 to 49) filling.icon_state = "[icon_state]-25"
if(50 to 74) filling.icon_state = "[icon_state]-50"
if(75 to 79) filling.icon_state = "[icon_state]-75"
if(80 to 90) filling.icon_state = "[icon_state]-80"
if(91 to INFINITY) filling.icon_state = "[icon_state]-100"
filling.color = reagents.get_color()
overlays += filling
if (!is_open_container())
var/image/lid = image(icon, src, "lid_bottle")
overlays += lid
/obj/item/weapon/reagent_containers/glass/bottle/inaprovaline
name = "inaprovaline bottle"
desc = "A small bottle. Contains inaprovaline - used to stabilize patients."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("inaprovaline" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/toxin
name = "toxin bottle"
desc = "A small bottle of toxins. Do not drink, it is poisonous."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-3"
prefill = list("toxin" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/cyanide
name = "cyanide bottle"
desc = "A small bottle of cyanide. Bitter almonds?"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-3"
prefill = list("cyanide" = 30) //volume changed to match chloral
/obj/item/weapon/reagent_containers/glass/bottle/stoxin
name = "soporific bottle"
desc = "A small bottle of soporific. Just the fumes make you sleepy."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-3"
prefill = list("stoxin" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/chloralhydrate
name = "chloral hydrate bottle"
desc = "A small bottle of Choral Hydrate. Mickey's Favorite!"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-3"
prefill = list("chloralhydrate" = 30) //Intentionally low since it is so strong. Still enough to knock someone out.
/obj/item/weapon/reagent_containers/glass/bottle/antitoxin
name = "dylovene bottle"
desc = "A small bottle of dylovene. Counters poisons, and repairs damage. A wonder drug."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("anti_toxin" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/mutagen
name = "unstable mutagen bottle"
desc = "A small bottle of unstable mutagen. Randomly changes the DNA structure of whoever comes in contact."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-1"
prefill = list("mutagen" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/ammonia
name = "ammonia bottle"
desc = "A small bottle."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-1"
prefill = list("ammonia" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/eznutrient
name = "\improper EZ NUtrient bottle"
desc = "A small bottle."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("eznutrient" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/left4zed
name = "\improper Left-4-Zed bottle"
desc = "A small bottle."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("left4zed" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/robustharvest
name = "\improper Robust Harvest"
desc = "A small bottle."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("robustharvest" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/diethylamine
name = "diethylamine bottle"
desc = "A small bottle."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("diethylamine" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/pacid
name = "polytrinic acid bottle"
desc = "A small bottle. Contains a small amount of Polytrinic Acid"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("pacid" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/adminordrazine
name = "adminordrazine bottle"
desc = "A small bottle. Contains the liquid essence of the gods."
icon = 'icons/obj/drinks.dmi'
icon_state = "holyflask"
prefill = list("adminordrazine" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/capsaicin
name = "capsaicin bottle"
desc = "A small bottle. Contains hot sauce."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("capsaicin" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/frostoil
name = "frost oil bottle"
desc = "A small bottle. Contains cold sauce."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("frostoil" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/biomass
name = "biomass bottle"
desc = "A bottle of raw biomass! Gross!"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-3"
prefill = list("biomass" = 60)
@@ -1,25 +1,25 @@
/obj/item/weapon/reagent_containers/glass/bottle/robot
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,25,30,50,100)
flags = OPENCONTAINER
volume = 60
var/reagent = ""
/obj/item/weapon/reagent_containers/glass/bottle/robot/inaprovaline
name = "internal inaprovaline bottle"
desc = "A small bottle. Contains inaprovaline - used to stabilize patients."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
reagent = "inaprovaline"
prefill = list("inaprovaline" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/robot/antitoxin
name = "internal anti-toxin bottle"
desc = "A small bottle of Anti-toxins. Counters poisons, and repairs damage, a wonder drug."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
reagent = "anti_toxin"
prefill = list("anti_toxin" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/robot
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,25,30,50,100)
flags = OPENCONTAINER
volume = 60
var/reagent = ""
/obj/item/weapon/reagent_containers/glass/bottle/robot/inaprovaline
name = "internal inaprovaline bottle"
desc = "A small bottle. Contains inaprovaline - used to stabilize patients."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
reagent = "inaprovaline"
prefill = list("inaprovaline" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/robot/antitoxin
name = "internal anti-toxin bottle"
desc = "A small bottle of Anti-toxins. Counters poisons, and repairs damage, a wonder drug."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
reagent = "anti_toxin"
prefill = list("anti_toxin" = 60)
@@ -1,236 +1,236 @@
/obj/machinery/gibber
name = "gibber"
desc = "The name isn't descriptive enough?"
icon = 'icons/obj/kitchen.dmi'
icon_state = "grinder"
density = 1
anchored = 1
req_access = list(access_kitchen,access_morgue)
var/operating = 0 //Is it on?
var/dirty = 0 // Does it need cleaning?
var/mob/living/occupant // Mob who has been put inside
var/gib_time = 40 // Time from starting until meat appears
var/gib_throw_dir = WEST // Direction to spit meat and gibs in.
use_power = 1
idle_power_usage = 2
active_power_usage = 500
//auto-gibs anything that bumps into it
/obj/machinery/gibber/autogibber
var/turf/input_plate
/obj/machinery/gibber/autogibber/New()
..()
spawn(5)
for(var/i in cardinal)
var/obj/machinery/mineral/input/input_obj = locate( /obj/machinery/mineral/input, get_step(src.loc, i) )
if(input_obj)
if(isturf(input_obj.loc))
input_plate = input_obj.loc
gib_throw_dir = i
qdel(input_obj)
break
if(!input_plate)
log_misc("a [src] didn't find an input plate.")
return
/obj/machinery/gibber/autogibber/Bumped(var/atom/A)
if(!input_plate) return
if(ismob(A))
var/mob/M = A
if(M.loc == input_plate
)
M.loc = src
M.gib()
/obj/machinery/gibber/New()
..()
src.overlays += image('icons/obj/kitchen.dmi', "grjam")
/obj/machinery/gibber/update_icon()
overlays.Cut()
if (dirty)
src.overlays += image('icons/obj/kitchen.dmi', "grbloody")
if(stat & (NOPOWER|BROKEN))
return
if (!occupant)
src.overlays += image('icons/obj/kitchen.dmi', "grjam")
else if (operating)
src.overlays += image('icons/obj/kitchen.dmi', "gruse")
else
src.overlays += image('icons/obj/kitchen.dmi', "gridle")
/obj/machinery/gibber/relaymove(mob/user as mob)
src.go_out()
return
/obj/machinery/gibber/attack_hand(mob/user as mob)
if(stat & (NOPOWER|BROKEN))
return
if(operating)
user << "<span class='danger'>The gibber is locked and running, wait for it to finish.</span>"
return
else
src.startgibbing(user)
/obj/machinery/gibber/examine()
..()
usr << "The safety guard is [emagged ? "<span class='danger'>disabled</span>" : "enabled"]."
/obj/machinery/gibber/emag_act(var/remaining_charges, var/mob/user)
emagged = !emagged
user << "<span class='danger'>You [emagged ? "disable" : "enable"] the gibber safety guard.</span>"
return 1
/obj/machinery/gibber/attackby(var/obj/item/W, var/mob/user)
var/obj/item/weapon/grab/G = W
if(default_unfasten_wrench(user, W, 40))
return
if(!istype(G))
return ..()
if(G.state < 2)
user << "<span class='danger'>You need a better grip to do that!</span>"
return
move_into_gibber(user,G.affecting)
// Grab() process should clean up the grab item, no need to del it.
/obj/machinery/gibber/MouseDrop_T(mob/target, mob/user)
if(user.stat || user.restrained())
return
move_into_gibber(user,target)
/obj/machinery/gibber/proc/move_into_gibber(var/mob/user,var/mob/living/victim)
if(src.occupant)
user << "<span class='danger'>The gibber is full, empty it first!</span>"
return
if(operating)
user << "<span class='danger'>The gibber is locked and running, wait for it to finish.</span>"
return
if(!(istype(victim, /mob/living/carbon)) && !(istype(victim, /mob/living/simple_animal)) )
user << "<span class='danger'>This is not suitable for the gibber!</span>"
return
if(istype(victim,/mob/living/carbon/human) && !emagged)
user << "<span class='danger'>The gibber safety guard is engaged!</span>"
return
if(victim.abiotic(1))
user << "<span class='danger'>Subject may not have abiotic items on.</span>"
return
user.visible_message("<span class='danger'>[user] starts to put [victim] into the gibber!</span>")
src.add_fingerprint(user)
if(do_after(user, 30) && victim.Adjacent(src) && user.Adjacent(src) && victim.Adjacent(user) && !occupant)
user.visible_message("<span class='danger'>[user] stuffs [victim] into the gibber!</span>")
if(victim.client)
victim.client.perspective = EYE_PERSPECTIVE
victim.client.eye = src
victim.loc = src
src.occupant = victim
update_icon()
/obj/machinery/gibber/verb/eject()
set category = "Object"
set name = "Empty Gibber"
set src in oview(1)
if (usr.stat != 0)
return
src.go_out()
add_fingerprint(usr)
return
/obj/machinery/gibber/proc/go_out()
if(operating || !src.occupant)
return
for(var/obj/O in src)
O.loc = src.loc
if (src.occupant.client)
src.occupant.client.eye = src.occupant.client.mob
src.occupant.client.perspective = MOB_PERSPECTIVE
src.occupant.loc = src.loc
src.occupant = null
update_icon()
return
/obj/machinery/gibber/proc/startgibbing(mob/user as mob)
if(src.operating)
return
if(!src.occupant)
visible_message("<span class='danger'>You hear a loud metallic grinding sound.</span>")
return
use_power(1000)
visible_message("<span class='danger'>You hear a loud [occupant.isSynthetic() ? "metallic" : "squelchy"] grinding sound.</span>")
src.operating = 1
update_icon()
var/slab_name = occupant.name
var/slab_count = 3
var/slab_type = /obj/item/weapon/reagent_containers/food/snacks/meat
var/slab_nutrition = src.occupant.nutrition / 15
// Some mobs have specific meat item types.
if(istype(src.occupant,/mob/living/simple_animal))
var/mob/living/simple_animal/critter = src.occupant
if(critter.meat_amount)
slab_count = critter.meat_amount
if(critter.meat_type)
slab_type = critter.meat_type
else if(istype(src.occupant,/mob/living/carbon/human))
var/mob/living/carbon/human/H = occupant
slab_name = src.occupant.real_name
slab_type = H.isSynthetic() ? /obj/item/stack/material/steel : H.species.meat_type
// Small mobs don't give as much nutrition.
if(issmall(src.occupant))
slab_nutrition *= 0.5
slab_nutrition /= slab_count
for(var/i=1 to slab_count)
var/obj/item/weapon/reagent_containers/food/snacks/meat/new_meat = new slab_type(src, rand(3,8))
if(istype(new_meat))
new_meat.name = "[slab_name] [new_meat.name]"
new_meat.reagents.add_reagent("nutriment",slab_nutrition)
if(src.occupant.reagents)
src.occupant.reagents.trans_to_obj(new_meat, round(occupant.reagents.total_volume/slab_count,1))
add_attack_logs(user,occupant,"Used [src] to gib")
src.occupant.ghostize()
spawn(gib_time)
src.operating = 0
src.occupant.gib()
qdel(src.occupant)
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
operating = 0
for (var/obj/item/thing in contents)
// There's a chance that the gibber will fail to destroy some evidence.
if(istype(thing,/obj/item/organ) && prob(80))
qdel(thing)
continue
thing.forceMove(get_turf(thing)) // Drop it onto the turf for throwing.
thing.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(0,3),emagged ? 100 : 50) // Being pelted with bits of meat and bone would hurt.
update_icon()
/obj/machinery/gibber
name = "gibber"
desc = "The name isn't descriptive enough?"
icon = 'icons/obj/kitchen.dmi'
icon_state = "grinder"
density = 1
anchored = 1
req_access = list(access_kitchen,access_morgue)
var/operating = 0 //Is it on?
var/dirty = 0 // Does it need cleaning?
var/mob/living/occupant // Mob who has been put inside
var/gib_time = 40 // Time from starting until meat appears
var/gib_throw_dir = WEST // Direction to spit meat and gibs in.
use_power = 1
idle_power_usage = 2
active_power_usage = 500
//auto-gibs anything that bumps into it
/obj/machinery/gibber/autogibber
var/turf/input_plate
/obj/machinery/gibber/autogibber/New()
..()
spawn(5)
for(var/i in cardinal)
var/obj/machinery/mineral/input/input_obj = locate( /obj/machinery/mineral/input, get_step(src.loc, i) )
if(input_obj)
if(isturf(input_obj.loc))
input_plate = input_obj.loc
gib_throw_dir = i
qdel(input_obj)
break
if(!input_plate)
log_misc("a [src] didn't find an input plate.")
return
/obj/machinery/gibber/autogibber/Bumped(var/atom/A)
if(!input_plate) return
if(ismob(A))
var/mob/M = A
if(M.loc == input_plate
)
M.loc = src
M.gib()
/obj/machinery/gibber/New()
..()
src.overlays += image('icons/obj/kitchen.dmi', "grjam")
/obj/machinery/gibber/update_icon()
overlays.Cut()
if (dirty)
src.overlays += image('icons/obj/kitchen.dmi', "grbloody")
if(stat & (NOPOWER|BROKEN))
return
if (!occupant)
src.overlays += image('icons/obj/kitchen.dmi', "grjam")
else if (operating)
src.overlays += image('icons/obj/kitchen.dmi', "gruse")
else
src.overlays += image('icons/obj/kitchen.dmi', "gridle")
/obj/machinery/gibber/relaymove(mob/user as mob)
src.go_out()
return
/obj/machinery/gibber/attack_hand(mob/user as mob)
if(stat & (NOPOWER|BROKEN))
return
if(operating)
user << "<span class='danger'>The gibber is locked and running, wait for it to finish.</span>"
return
else
src.startgibbing(user)
/obj/machinery/gibber/examine()
..()
usr << "The safety guard is [emagged ? "<span class='danger'>disabled</span>" : "enabled"]."
/obj/machinery/gibber/emag_act(var/remaining_charges, var/mob/user)
emagged = !emagged
user << "<span class='danger'>You [emagged ? "disable" : "enable"] the gibber safety guard.</span>"
return 1
/obj/machinery/gibber/attackby(var/obj/item/W, var/mob/user)
var/obj/item/weapon/grab/G = W
if(default_unfasten_wrench(user, W, 40))
return
if(!istype(G))
return ..()
if(G.state < 2)
user << "<span class='danger'>You need a better grip to do that!</span>"
return
move_into_gibber(user,G.affecting)
// Grab() process should clean up the grab item, no need to del it.
/obj/machinery/gibber/MouseDrop_T(mob/target, mob/user)
if(user.stat || user.restrained())
return
move_into_gibber(user,target)
/obj/machinery/gibber/proc/move_into_gibber(var/mob/user,var/mob/living/victim)
if(src.occupant)
user << "<span class='danger'>The gibber is full, empty it first!</span>"
return
if(operating)
user << "<span class='danger'>The gibber is locked and running, wait for it to finish.</span>"
return
if(!(istype(victim, /mob/living/carbon)) && !(istype(victim, /mob/living/simple_animal)) )
user << "<span class='danger'>This is not suitable for the gibber!</span>"
return
if(istype(victim,/mob/living/carbon/human) && !emagged)
user << "<span class='danger'>The gibber safety guard is engaged!</span>"
return
if(victim.abiotic(1))
user << "<span class='danger'>Subject may not have abiotic items on.</span>"
return
user.visible_message("<span class='danger'>[user] starts to put [victim] into the gibber!</span>")
src.add_fingerprint(user)
if(do_after(user, 30) && victim.Adjacent(src) && user.Adjacent(src) && victim.Adjacent(user) && !occupant)
user.visible_message("<span class='danger'>[user] stuffs [victim] into the gibber!</span>")
if(victim.client)
victim.client.perspective = EYE_PERSPECTIVE
victim.client.eye = src
victim.loc = src
src.occupant = victim
update_icon()
/obj/machinery/gibber/verb/eject()
set category = "Object"
set name = "Empty Gibber"
set src in oview(1)
if (usr.stat != 0)
return
src.go_out()
add_fingerprint(usr)
return
/obj/machinery/gibber/proc/go_out()
if(operating || !src.occupant)
return
for(var/obj/O in src)
O.loc = src.loc
if (src.occupant.client)
src.occupant.client.eye = src.occupant.client.mob
src.occupant.client.perspective = MOB_PERSPECTIVE
src.occupant.loc = src.loc
src.occupant = null
update_icon()
return
/obj/machinery/gibber/proc/startgibbing(mob/user as mob)
if(src.operating)
return
if(!src.occupant)
visible_message("<span class='danger'>You hear a loud metallic grinding sound.</span>")
return
use_power(1000)
visible_message("<span class='danger'>You hear a loud [occupant.isSynthetic() ? "metallic" : "squelchy"] grinding sound.</span>")
src.operating = 1
update_icon()
var/slab_name = occupant.name
var/slab_count = 3
var/slab_type = /obj/item/weapon/reagent_containers/food/snacks/meat
var/slab_nutrition = src.occupant.nutrition / 15
// Some mobs have specific meat item types.
if(istype(src.occupant,/mob/living/simple_animal))
var/mob/living/simple_animal/critter = src.occupant
if(critter.meat_amount)
slab_count = critter.meat_amount
if(critter.meat_type)
slab_type = critter.meat_type
else if(istype(src.occupant,/mob/living/carbon/human))
var/mob/living/carbon/human/H = occupant
slab_name = src.occupant.real_name
slab_type = H.isSynthetic() ? /obj/item/stack/material/steel : H.species.meat_type
// Small mobs don't give as much nutrition.
if(issmall(src.occupant))
slab_nutrition *= 0.5
slab_nutrition /= slab_count
for(var/i=1 to slab_count)
var/obj/item/weapon/reagent_containers/food/snacks/meat/new_meat = new slab_type(src, rand(3,8))
if(istype(new_meat))
new_meat.name = "[slab_name] [new_meat.name]"
new_meat.reagents.add_reagent("nutriment",slab_nutrition)
if(src.occupant.reagents)
src.occupant.reagents.trans_to_obj(new_meat, round(occupant.reagents.total_volume/slab_count,1))
add_attack_logs(user,occupant,"Used [src] to gib")
src.occupant.ghostize()
spawn(gib_time)
src.operating = 0
src.occupant.gib()
qdel(src.occupant)
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
operating = 0
for (var/obj/item/thing in contents)
// There's a chance that the gibber will fail to destroy some evidence.
if(istype(thing,/obj/item/organ) && prob(80))
qdel(thing)
continue
thing.forceMove(get_turf(thing)) // Drop it onto the turf for throwing.
thing.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(0,3),emagged ? 100 : 50) // Being pelted with bits of meat and bone would hurt.
update_icon()
@@ -179,7 +179,7 @@
qdel(H)
spawn(50)
new /obj/item/honey_frame(loc)
new /obj/item/stack/wax(loc)
new /obj/item/stack/material/wax(loc)
honey += processing
processing = 0
icon_state = "centrifuge"
@@ -234,14 +234,14 @@
qdel(src)
return
/obj/item/stack/wax
/obj/item/stack/material/wax
name = "wax"
singular_name = "wax piece"
desc = "Soft substance produced by bees. Used to make candles."
icon = 'icons/obj/beekeeping.dmi'
icon_state = "wax"
/obj/item/stack/wax/New()
/obj/item/stack/material/wax/New()
..()
recipes = wax_recipes
@@ -52,7 +52,6 @@
/obj/item/device/electronic_assembly/proc/resolve_nano_host()
return src
/obj/item/device/electronic_assembly/proc/check_interactivity(mob/user)
if(!CanInteract(user, physical_state))
return 0
+1 -1
View File
@@ -157,7 +157,7 @@ var/global/use_preloader = FALSE
++turfsSkipped
#endif
CHECK_TICK
maxx = max(maxx, ++xcrd)
maxx = max(maxx, xcrd++)
key_list[++key_list.len] = line_keys
// Rotate the list according to orientation
+1
View File
@@ -9,6 +9,7 @@
/obj/item/weapon/mining_scanner/attack_self(mob/user as mob)
user << "You begin sweeping \the [src] about, scanning for metal deposits."
playsound(loc, 'sound/items/goggles_charge.ogg', 50, 1, -6)
if(!do_after(user, 50))
return
+64 -2
View File
@@ -11,6 +11,8 @@
density = TRUE
anchored = TRUE
var/obj/item/weapon/card/id/inserted_id // Inserted ID card, for points
var/obj/machinery/mineral/processing_unit/machine = null
var/show_all_ores = FALSE
@@ -23,11 +25,27 @@
log_debug("Ore processing machine console at [src.x], [src.y], [src.z] could not find its machine!")
qdel(src)
/obj/machinery/mineral/processing_unit_console/Destroy()
if(inserted_id)
inserted_id.forceMove(loc) //Prevents deconstructing from deleting whatever ID was inside it.
. = ..()
/obj/machinery/mineral/processing_unit_console/attack_hand(mob/user)
if(..())
return
interact(user)
/obj/machinery/mineral/processing_unit_console/attackby(var/obj/item/I, var/mob/user)
if(istype(I, /obj/item/weapon/card/id))
if(!powered())
return
if(!inserted_id && user.unEquip(I))
I.forceMove(src)
inserted_id = I
interact(user)
return
..()
/obj/machinery/mineral/processing_unit_console/interact(mob/user)
if(..())
return
@@ -40,6 +58,13 @@
var/dat = "<h1>Ore processor console</h1>"
dat += "Current unclaimed points: [machine.points]<br>"
if(istype(inserted_id))
dat += "You have [inserted_id.mining_points] mining points collected. <A href='?src=\ref[src];choice=eject'>Eject ID.</A><br>"
dat += "<A href='?src=\ref[src];choice=claim'>Claim points.</A><br>"
else
dat += "No ID inserted. <A href='?src=\ref[src];choice=insert'>Insert ID.</A><br>"
dat += "<hr><table>"
for(var/ore in machine.ores_processing)
@@ -96,6 +121,26 @@
show_all_ores = !show_all_ores
if(href_list["choice"])
if(istype(inserted_id))
if(href_list["choice"] == "eject")
usr.put_in_hands(inserted_id)
inserted_id = null
if(href_list["choice"] == "claim")
if(access_mining_station in inserted_id.access)
inserted_id.mining_points += machine.points
machine.points = 0
else
to_chat(usr, "<span class='warning'>Required access not found.</span>")
else if(href_list["choice"] == "insert")
var/obj/item/weapon/card/id/I = usr.get_active_hand()
if(istype(I))
usr.drop_item()
I.forceMove(src)
inserted_id = I
else
to_chat(usr, "<span class='warning'>No valid ID.</span>")
src.updateUsrDialog()
return
@@ -118,6 +163,19 @@
var/static/list/alloy_data
var/active = FALSE
var/points = 0
var/static/list/ore_values = list(
"sand" = 1,
"hematite" = 1,
"carbon" = 1,
"phoron" = 15,
"silver" = 16,
"gold" = 18,
"uranium" = 30,
"diamond" = 50,
"platinum" = 40,
"mhydrogen" = 40)
/obj/machinery/mineral/processing_unit/New()
..()
// initialize static alloy_data list
@@ -148,7 +206,11 @@
/obj/machinery/mineral/processing_unit/process()
if (!src.output || !src.input) return
if (!src.output || !src.input)
return
if(panel_open || !powered())
return
var/list/tick_alloys = list()
@@ -158,7 +220,7 @@
if(!O) break
if(!isnull(ores_stored[O.material]))
ores_stored[O.material]++
points += ore_values[O.material] // Give Points!
qdel(O)
if(!active)
-5
View File
@@ -30,11 +30,6 @@
var/excavation_amount = 200
/obj/item/weapon/pickaxe/hammer
name = "sledgehammer"
//icon_state = "sledgehammer" Waiting on sprite
desc = "A mining hammer made of reinforced metal. You feel like smashing your boss in the face with this."
/obj/item/weapon/pickaxe/silver
name = "silver pickaxe"
icon_state = "spickaxe"
+2
View File
@@ -452,6 +452,8 @@ var/list/mining_overlay_cache = list()
//update overlays displaying excavation level
if( !(excav_overlay && excavation_level > 0) || update_excav_overlay )
var/excav_quadrant = round(excavation_level / 25) + 1
if(excav_quadrant > 5)
excav_quadrant = 5
cut_overlay(excav_overlay)
excav_overlay = "overlay_excv[excav_quadrant]_[rand(1,3)]"
add_overlay(excav_overlay)
@@ -0,0 +1,12 @@
#ifndef T_BOARD
#error T_BOARD macro is not defined but we need it!
#endif
/obj/item/weapon/circuitboard/mining_equipment_vendor
name = T_BOARD("Mining Equipment Vendor")
board_type = new /datum/frame/frame_types/machine
build_path = /obj/machinery/mineral/equipment_vendor
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 3)
req_components = list(
/obj/item/weapon/stock_parts/console_screen = 1,
/obj/item/weapon/stock_parts/matter_bin = 3)
@@ -0,0 +1,194 @@
/**********************Mining Equipment Locker**************************/
/obj/machinery/mineral/equipment_vendor
name = "mining equipment vendor"
desc = "An equipment vendor for miners, points collected at an ore redemption machine can be spent here."
icon = 'icons/obj/machines/mining_machines.dmi'
icon_state = "mining"
density = TRUE
anchored = TRUE
circuit = /obj/item/weapon/circuitboard/mining_equipment_vendor
var/icon_deny = "mining-deny"
var/obj/item/weapon/card/id/inserted_id
var/list/prize_list = list(
new /datum/data/mining_equipment("1 Marker Beacon", /obj/item/stack/marker_beacon, 10),
new /datum/data/mining_equipment("10 Marker Beacons", /obj/item/stack/marker_beacon/ten, 100),
new /datum/data/mining_equipment("30 Marker Beacons", /obj/item/stack/marker_beacon/thirty, 300),
new /datum/data/mining_equipment("Whiskey", /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey, 125),
new /datum/data/mining_equipment("Absinthe", /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe, 125),
new /datum/data/mining_equipment("Cigar", /obj/item/clothing/mask/smokable/cigarette/cigar/havana, 150),
new /datum/data/mining_equipment("Soap", /obj/item/weapon/soap/nanotrasen, 200),
new /datum/data/mining_equipment("Laser Pointer", /obj/item/device/laser_pointer, 900),
new /datum/data/mining_equipment("Plush Toy", /obj/random/plushie, 300),
// new /datum/data/mining_equipment("Fulton Beacon", /obj/item/fulton_core, 500),
new /datum/data/mining_equipment("Point Transfer Card", /obj/item/weapon/card/mining_point_card, 500),
// new /datum/data/mining_equipment("Fulton Pack", /obj/item/extraction_pack, 1200),
new /datum/data/mining_equipment("Silver Pickaxe", /obj/item/weapon/pickaxe/silver, 1200),
// new /datum/data/mining_equipment("Space Cash", /obj/item/weapon/spacecash/c1000, 2000),
// new /datum/data/mining_equipment("Industrial Hardsuit - Control Module", /obj/item/weapon/rig/industrial, 2000),
// new /datum/data/mining_equipment("Industrial Hardsuit - Plasma Cutter", /obj/item/rig_module/device/plasmacutter, 800),
// new /datum/data/mining_equipment("Industrial Hardsuit - Drill", /obj/item/rig_module/device/drill, 2000),
// new /datum/data/mining_equipment("Industrial Hardsuit - Ore Scanner", /obj/item/rig_module/device/orescanner, 1000),
// new /datum/data/mining_equipment("Industrial Hardsuit - Material Scanner", /obj/item/rig_module/vision/material, 500),
// new /datum/data/mining_equipment("Industrial Hardsuit - Maneuvering Jets", /obj/item/rig_module/maneuvering_jets, 1250),
// new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/weapon/pickaxe/diamond, 2000),
)
/datum/data/mining_equipment
var/equipment_name = "generic"
var/equipment_path = null
var/cost = 0
/datum/data/mining_equipment/New(name, path, cost)
src.equipment_name = name
src.equipment_path = path
src.cost = cost
/obj/machinery/power/quantumpad/initialize()
. = ..()
default_apply_parts()
/obj/machinery/mineral/equipment_vendor/power_change()
var/old_stat = stat
..()
if(old_stat != stat)
update_icon()
if(inserted_id && !powered())
visible_message("<span class='notice'>The ID slot indicator light flickers on \the [src] as it spits out a card before powering down.</span>")
inserted_id.forceMove(get_turf(src))
/obj/machinery/mineral/equipment_vendor/update_icon()
if(panel_open)
icon_state = "[initial(icon_state)]-open"
else if(powered())
icon_state = initial(icon_state)
else
icon_state = "[initial(icon_state)]-off"
/obj/machinery/mineral/equipment_vendor/attack_hand(mob/user)
if(..())
return
interact(user)
/obj/machinery/mineral/equipment_vendor/attack_ghost(mob/user)
interact(user)
/obj/machinery/mineral/equipment_vendor/interact(mob/user)
user.set_machine(src)
var/dat
dat +="<div class='statusDisplay'>"
if(istype(inserted_id))
dat += "You have [inserted_id.mining_points] mining points collected. <A href='?src=\ref[src];choice=eject'>Eject ID.</A><br>"
else
dat += "No ID inserted. <A href='?src=\ref[src];choice=insert'>Insert ID.</A><br>"
dat += "</div>"
dat += "<br><b>Equipment point cost list:</b><BR><table border='0' width='100%'>"
for(var/datum/data/mining_equipment/prize in prize_list)
dat += "<tr><td>[prize.equipment_name]</td><td>[prize.cost]</td><td><A href='?src=\ref[src];purchase=\ref[prize]'>Purchase</A></td></tr>"
dat += "</table>"
var/datum/browser/popup = new(user, "miningvendor", "Mining Equipment Vendor", 400, 600)
popup.set_content(dat)
popup.open()
/obj/machinery/mineral/equipment_vendor/Topic(href, href_list)
if(..())
return 1
if(href_list["choice"])
if(istype(inserted_id))
if(href_list["choice"] == "eject")
to_chat(usr, "<span class='notice'>You eject the ID from [src]'s card slot.</span>")
usr.put_in_hands(inserted_id)
inserted_id = null
else if(href_list["choice"] == "insert")
var/obj/item/weapon/card/id/I = usr.get_active_hand()
if(istype(I) && !inserted_id && usr.unEquip(I))
I.forceMove(src)
inserted_id = I
interact(usr)
to_chat(usr, "<span class='notice'>You insert the ID into [src]'s card slot.</span>")
else
to_chat(usr, "<span class='warning'>No valid ID.</span>")
flick(icon_deny, src)
if(href_list["purchase"])
if(istype(inserted_id))
var/datum/data/mining_equipment/prize = locate(href_list["purchase"])
if (!prize || !(prize in prize_list))
to_chat(usr, "<span class='warning'>Error: Invalid choice!</span>")
flick(icon_deny, src)
return
if(prize.cost > inserted_id.mining_points)
to_chat(usr, "<span class='warning'>Error: Insufficent points for [prize.equipment_name]!</span>")
flick(icon_deny, src)
else
inserted_id.mining_points -= prize.cost
to_chat(usr, "<span class='notice'>[src] clanks to life briefly before vending [prize.equipment_name]!</span>")
new prize.equipment_path(drop_location())
else
to_chat(usr, "<span class='warning'>Error: Please insert a valid ID!</span>")
flick(icon_deny, src)
updateUsrDialog()
/obj/machinery/mineral/equipment_vendor/attackby(obj/item/I, mob/user, params)
if(default_deconstruction_screwdriver(user, I))
updateUsrDialog()
return
if(default_part_replacement(user, I))
return
if(default_deconstruction_crowbar(user, I))
return
if(istype(I, /obj/item/mining_voucher))
if(!powered())
return
RedeemVoucher(I, user)
return
if(istype(I,/obj/item/weapon/card/id))
if(!powered())
return
else if(!inserted_id && user.unEquip(I))
I.forceMove(src)
inserted_id = I
interact(user)
return
..()
/obj/machinery/mineral/equipment_vendor/dismantle()
if(inserted_id)
inserted_id.forceMove(loc) //Prevents deconstructing the ORM from deleting whatever ID was inside it.
. = ..()
/obj/machinery/mineral/equipment_vendor/proc/RedeemVoucher(obj/item/mining_voucher/voucher, mob/redeemer)
var/selection = input(redeemer, "Pick your equipment", "Mining Voucher Redemption") as null|anything in list("Kinetic Accelerator", "Resonator", "Mining Drone", "Advanced Scanner", "Crusher")
if(!selection || !Adjacent(redeemer) || voucher.loc != redeemer)
return
// var/drop_location = drop_location()
// switch(selection)
// if("Kinetic Accelerator")
// new /obj/item/weapon/gun/energy/kinetic_accelerator(drop_location)
// if("Resonator")
// new /obj/item/resonator(drop_location)
// if("Mining Drone")
// new /obj/item/storage/box/drone_kit(drop_location)
// if("Advanced Scanner")
// new /obj/item/device/t_scanner/adv_mining_scanner(drop_location)
// if("Crusher")
// new /obj/item/twohanded/required/mining_hammer(drop_location)
qdel(voucher)
/obj/machinery/mineral/equipment_vendor/proc/new_prize(var/name, var/path, var/cost) // Generic proc for adding new entries. Good for abusing for FUN and PROFIT.
if(!cost)
cost = 100
if(!path)
path = /obj/item/stack/marker_beacon
if(!name)
name = "Generic Entry"
prize_list += new /datum/data/mining_equipment(name, path, cost)
/obj/machinery/mineral/equipment_vendor/ex_act(severity, target)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
if(prob(50 / severity) && severity < 3)
qdel(src)
@@ -0,0 +1,33 @@
/**********************Mining Equipment Locker Items**************************/
/**********************Mining Equipment Voucher**********************/
/obj/item/mining_voucher
name = "mining voucher"
desc = "A token to redeem a piece of equipment. Use it on a mining equipment vendor."
icon = 'icons/obj/mining.dmi'
icon_state = "mining_voucher"
w_class = ITEMSIZE_TINY
/**********************Mining Point Card**********************/
/obj/item/weapon/card/mining_point_card
name = "mining point card"
desc = "A small card preloaded with mining points. Swipe your ID card over it to transfer the points, then discard."
icon_state = "data"
var/points = 500
/obj/item/weapon/card/mining_point_card/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/card/id))
if(points)
var/obj/item/weapon/card/id/C = I
C.mining_points += points
to_chat(user, "<span class='info'>You transfer [points] points to [C].</span>")
points = 0
else
to_chat(user, "<span class='info'>There's no points left on [src].</span>")
..()
/obj/item/weapon/card/mining_point_card/examine(mob/user)
..(user)
to_chat(user, "There's [points] points on the card.")
+107
View File
@@ -0,0 +1,107 @@
/**********************Resonator**********************/
/obj/item/resonator
name = "resonator"
icon = 'icons/obj/mining.dmi'
icon_state = "resonator"
item_state = "resonator"
origin_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 3)
desc = "A handheld device that creates small fields of energy that resonate until they detonate, crushing rock. It can also be activated without a target to create a field at the user's location, to act as a delayed time trap. It's more effective in low temperature."
w_class = ITEMSIZE_NORMAL
force = 8
throwforce = 10
var/cooldown = 0
var/fieldsactive = 0
var/burst_time = 50
var/fieldlimit = 3
/obj/item/resonator/upgraded
name = "upgraded resonator"
desc = "An upgraded version of the resonator that can produce more fields at once."
icon_state = "resonator_u"
origin_tech = list(TECH_MATERIAL = 4, TECH_POWER = 3, TECH_MAGNET = 3, TECH_ENGINEERING = 3)
fieldlimit = 5
/obj/item/resonator/proc/CreateResonance(var/target, var/creator)
var/turf/T = get_turf(target)
if(locate(/obj/effect/resonance) in T)
return
if(fieldsactive < fieldlimit)
playsound(src,'sound/weapons/resonator_fire.ogg',50,1)
new /obj/effect/resonance(T, creator, burst_time)
fieldsactive++
spawn(burst_time)
fieldsactive--
/obj/item/resonator/attack_self(mob/user)
if(burst_time == 50)
burst_time = 30
to_chat(user, "<span class='info'>You set the resonator's fields to detonate after 3 seconds.</span>")
else
burst_time = 50
to_chat(user, "<span class='info'>You set the resonator's fields to detonate after 5 seconds.</span>")
/obj/item/resonator/afterattack(atom/target, mob/user, proximity_flag)
if(proximity_flag)
if(!check_allowed_items(target, 1))
return
CreateResonance(target, user)
/obj/effect/resonance
name = "resonance field"
desc = "A resonating field that significantly damages anything inside of it when the field eventually ruptures."
icon = 'icons/effects/effects.dmi'
icon_state = "shield1"
plane = MOB_PLANE
layer = ABOVE_MOB_LAYER
mouse_opacity = 0
var/resonance_damage = 20
/obj/effect/resonance/initialize(mapload, var/creator = null, var/timetoburst)
. = ..()
// Start small and grow to big size as we are about to burst
transform = matrix()*0.75
animate(src, transform = matrix()*1.5, time = timetoburst)
// Queue the actual bursting
spawn(timetoburst)
if(!QDELETED(src))
burst(creator)
/obj/effect/resonance/proc/burst(var/creator = null)
var/turf/T = get_turf(src)
if(!T)
return
playsound(src, 'sound/weapons/resonator_blast.ogg', 50, 1)
// Make the collapsing effect
new /obj/effect/temp_visual/resonance_crush(T)
// Mineral turfs get drilled!
if(istype(T, /turf/simulated/mineral))
var/turf/simulated/mineral/M = T
M.GetDrilled()
qdel(src)
return
// Otherwise we damage mobs! Boost damage if low tempreature
var/datum/gas_mixture/environment = T.return_air()
if(environment.temperature < 250)
name = "strong resonance field"
resonance_damage = 50
for(var/mob/living/L in src.loc)
if(creator)
add_attack_logs(creator, L, "used a resonator field on")
to_chat(L, "<span class='danger'>\The [src] ruptured with you in it!</span>")
L.apply_damage(resonance_damage, BRUTE)
qdel(src)
/obj/effect/temp_visual/resonance_crush
icon_state = "shield1"
plane = MOB_PLANE
layer = ABOVE_MOB_LAYER
duration = 4
/obj/effect/temp_visual/resonance_crush/initialize()
. = ..()
transform = matrix()*1.5
animate(src, transform = matrix()*0.1, alpha = 50, time = 4)
@@ -156,6 +156,7 @@ Works together with spawning an observer, noted above.
if(!client) return 0
handle_regular_hud_updates()
handle_vision()
/mob/proc/ghostize(var/can_reenter_corpse = 1)
if(key)
+1
View File
@@ -103,6 +103,7 @@
updateicon()
handle_regular_hud_updates()
handle_vision()
if(ticker && ticker.mode)
ticker.mode.check_win()
+1 -1
View File
@@ -3,7 +3,7 @@
desc = "A little cleaning robot, it looks so excited!"
icon_state = "cleanbot0"
req_one_access = list(access_robotics, access_janitor)
botcard_access = list(access_janitor, access_maint_tunnels)
botcard_access = list(access_janitor)
locked = 0 // Start unlocked so roboticist can set them to patrol.
wait_if_pulled = 1
@@ -38,7 +38,8 @@
..()
/datum/mob_descriptor/proc/get_third_person_message_start(var/datum/gender/my_gender)
return "[my_gender.He] [my_gender.is]"
return "They are"
// return "[my_gender.He] [my_gender.is]" // Doesn't respect ambiguous_genders species var, can't figure out a fix at the moment
/datum/mob_descriptor/proc/get_first_person_message_start()
return "You are"
@@ -105,3 +106,4 @@
var/maxval = LAZYLEN(comparative_value_descriptors_larger)
value = Clamp(ceil(value * maxval), 1, maxval)
return comparative_value_descriptors_larger[value]
@@ -727,7 +727,7 @@
src << "blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, cry, custom, deathgasp, drool, eyebrow, fastsway/qwag, \
frown, gasp, giggle, glare-(none)/mob, grin, groan, grumble, handshake, hug-(none)/mob, laugh, look-(none)/mob, moan, mumble, nod, pale, point-atom, \
raise, salute, scream, sneeze, shake, shiver, shrug, sigh, signal-#1-10, slap-(none)/mob, smile, sneeze, sniff, snore, stare-(none)/mob, stopsway/swag, sway/wag, swish, tremble, twitch, \
twitch_v, vomit, whimper, wink, yawn. Synthetics: beep, buzz, yes, no, rcough, rsneeze, ping"
twitch_v, vomit, whimper, wink, yawn. Synthetics: beep, buzz, yess, no, rcough, rsneeze, ping"
else
src << "<font color='blue'>Unusable emote '[act]'. Say *help for a list.</font>"
@@ -421,15 +421,16 @@
msg += "*---------*</span><br>"
msg += applying_pressure
if(pose)
if(!findtext(pose, regex("\[.?!]$"))) // Will be zero if the last character is not a member of [.?!]
pose = addtext(pose,".") //Makes sure all emotes end with a period.
msg += "[T.He] [pose]"
var/show_descs = show_descriptors_to(user)
if(show_descs)
msg += "<span class='notice'>[jointext(show_descs, "<br>")]</span>"
if(pose)
if(!findtext(pose, regex("\[.?!]$"))) // Will be zero if the last character is not a member of [.?!]
pose = addtext(pose,".") //Makes sure all emotes end with a period.
msg += "<br>[T.He] [pose]"
to_chat(user, jointext(msg, null))
//Helper procedure. Called by /mob/living/carbon/human/examine() and /mob/living/carbon/human/Topic() to determine HUD access to security and medical records.
+93 -91
View File
@@ -1066,38 +1066,41 @@
var/obj/machinery/camera/cam = client.eye
client.screen |= cam.client_huds
if(stat != DEAD)
if(stat == UNCONSCIOUS && health <= 0)
//Critical damage passage overlay
if(stat == DEAD) //Dead
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(healths) healths.icon_state = "health7" //DEAD healthmeter
else if(stat == UNCONSCIOUS && health <= 0) //Crit
//Critical damage passage overlay
var/severity = 0
switch(health)
if(-20 to -10) severity = 1
if(-30 to -20) severity = 2
if(-40 to -30) severity = 3
if(-50 to -40) severity = 4
if(-60 to -50) severity = 5
if(-70 to -60) severity = 6
if(-80 to -70) severity = 7
if(-90 to -80) severity = 8
if(-95 to -90) severity = 9
if(-INFINITY to -95) severity = 10
overlay_fullscreen("crit", /obj/screen/fullscreen/crit, severity)
else //Alive
clear_fullscreen("crit")
//Oxygen damage overlay
if(oxyloss)
var/severity = 0
switch(health)
if(-20 to -10) severity = 1
if(-30 to -20) severity = 2
if(-40 to -30) severity = 3
if(-50 to -40) severity = 4
if(-60 to -50) severity = 5
if(-70 to -60) severity = 6
if(-80 to -70) severity = 7
if(-90 to -80) severity = 8
if(-95 to -90) severity = 9
if(-INFINITY to -95) severity = 10
overlay_fullscreen("crit", /obj/screen/fullscreen/crit, severity)
switch(oxyloss)
if(10 to 20) severity = 1
if(20 to 25) severity = 2
if(25 to 30) severity = 3
if(30 to 35) severity = 4
if(35 to 40) severity = 5
if(40 to 45) severity = 6
if(45 to INFINITY) severity = 7
overlay_fullscreen("oxy", /obj/screen/fullscreen/oxy, severity)
else
clear_fullscreen("crit")
//Oxygen damage overlay
if(oxyloss)
var/severity = 0
switch(oxyloss)
if(10 to 20) severity = 1
if(20 to 25) severity = 2
if(25 to 30) severity = 3
if(30 to 35) severity = 4
if(35 to 40) severity = 5
if(40 to 45) severity = 6
if(45 to INFINITY) severity = 7
overlay_fullscreen("oxy", /obj/screen/fullscreen/oxy, severity)
else
clear_fullscreen("oxy")
clear_fullscreen("oxy")
//Fire and Brute damage overlay (BSSR)
var/hurtdamage = src.getShockBruteLoss() + src.getShockFireLoss() + damageoverlaytemp //Doesn't call the overlay if you can't actually feel it
@@ -1115,66 +1118,6 @@
else
clear_fullscreen("brute")
if( stat == DEAD )
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS|SEE_SELF
see_in_dark = 8
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(healths) healths.icon_state = "health7" //DEAD healthmeter
if(client)
if(client.view != world.view) // If mob dies while zoomed in with device, unzoom them.
for(var/obj/item/item in contents)
if(item.zoom)
item.zoom()
break
else
sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS)
see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : see_invisible_default
if(XRAY in mutations)
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
see_in_dark = 8
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(seer==1)
var/obj/effect/rune/R = locate() in loc
if(R && R.word1 == cultwords["see"] && R.word2 == cultwords["hell"] && R.word3 == cultwords["join"])
see_invisible = SEE_INVISIBLE_CULT
else
see_invisible = see_invisible_default
seer = 0
if(!seedarkness)
sight = species.get_vision_flags(src)
see_in_dark = 8
see_invisible = SEE_INVISIBLE_NOLIGHTING
else
sight = species.get_vision_flags(src)
see_in_dark = species.darksight
see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : see_invisible_default
var/tmp/glasses_processed = 0
var/obj/item/weapon/rig/rig = back
if(istype(rig) && rig.visor)
if(!rig.helmet || (head && rig.helmet == head))
if(rig.visor && rig.visor.vision && rig.visor.active && rig.visor.vision.glasses)
glasses_processed = 1
process_glasses(rig.visor.vision.glasses)
if(glasses && !glasses_processed)
glasses_processed = 1
process_glasses(glasses)
if(XRAY in mutations)
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
see_in_dark = 8
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(!glasses_processed && (species.get_vision_flags(src) > 0))
sight |= species.get_vision_flags(src)
if(!seer && !glasses_processed && seedarkness)
see_invisible = see_invisible_default
if(healths)
if (chem_effects[CE_PAINKILLER] > 100)
healths.icon_state = "health_numb"
@@ -1320,11 +1263,70 @@
if(found_welder)
client.screen |= global_hud.darkMask
/mob/living/carbon/human/handle_vision()
if(stat == DEAD)
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS|SEE_SELF
see_in_dark = 8
if(client)
if(client.view != world.view) // If mob dies while zoomed in with device, unzoom them.
for(var/obj/item/item in contents)
if(item.zoom)
item.zoom()
break
else //We aren't dead
sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS)
see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : see_invisible_default
if(XRAY in mutations)
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
see_in_dark = 8
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(seer==1)
var/obj/effect/rune/R = locate() in loc
if(R && R.word1 == cultwords["see"] && R.word2 == cultwords["hell"] && R.word3 == cultwords["join"])
see_invisible = SEE_INVISIBLE_CULT
else
see_invisible = see_invisible_default
seer = 0
if(!seedarkness)
sight = species.get_vision_flags(src)
see_in_dark = 8
see_invisible = SEE_INVISIBLE_NOLIGHTING
else
sight = species.get_vision_flags(src)
see_in_dark = species.darksight
see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : see_invisible_default
var/tmp/glasses_processed = 0
var/obj/item/weapon/rig/rig = back
if(istype(rig) && rig.visor && !looking_elsewhere)
if(!rig.helmet || (head && rig.helmet == head))
if(rig.visor && rig.visor.vision && rig.visor.active && rig.visor.vision.glasses)
glasses_processed = 1
process_glasses(rig.visor.vision.glasses)
if(glasses && !glasses_processed && !looking_elsewhere)
glasses_processed = 1
process_glasses(glasses)
if(XRAY in mutations)
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
see_in_dark = 8
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(!glasses_processed && (species.get_vision_flags(src) > 0))
sight |= species.get_vision_flags(src)
if(!seer && !glasses_processed && seedarkness)
see_invisible = see_invisible_default
if(machine)
var/viewflags = machine.check_eye(src)
if(viewflags < 0)
reset_view(null, 0)
else if(viewflags)
else if(viewflags && !looking_elsewhere)
sight |= viewflags
else if(eyeobj)
if(eyeobj.owner != src)
@@ -237,6 +237,7 @@
var/list/descriptor_datums = list()
for(var/desctype in descriptors)
var/datum/mob_descriptor/descriptor = new desctype
descriptor.comparison_offset = descriptors[desctype]
descriptor_datums[descriptor.name] = descriptor
descriptors = descriptor_datums
@@ -43,6 +43,7 @@
slowdown = -1
snow_movement = -2 // Ignores light snow
item_slowdown_mod = 2 // Tiny birds don't like heavy things
total_health = 50
brute_mod = 1.35
burn_mod = 1.35
@@ -122,6 +123,11 @@
/mob/living/proc/hide
)
descriptors = list(
/datum/mob_descriptor/height = -3,
/datum/mob_descriptor/build = -3
)
/datum/species/teshari/equip_survival_gear(var/mob/living/carbon/human/H)
..()
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H),slot_shoes)
@@ -47,7 +47,7 @@
brute_mod = 0.85
burn_mod = 0.85
metabolic_rate = 0.85
item_slowdown_mod = 0.5
item_slowdown_mod = 0.25
mob_size = MOB_LARGE
blood_volume = 840
bloodloss_rate = 0.75
@@ -324,7 +324,7 @@
siemens_coefficient = 0.3
show_ssd = "completely quiescent"
health_hud_intensity = 2.5
item_slowdown_mod = 0.25
item_slowdown_mod = 0.1
num_alternate_languages = 2
name_language = LANGUAGE_ROOTLOCAL

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