mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2026-07-18 19:53:00 +01:00
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:
@@ -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
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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, " ")
|
||||
|
||||
@@ -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
@@ -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")
|
||||
@@ -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
@@ -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]"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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]"].")
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>")
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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"]")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
@@ -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")
|
||||
@@ -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)]->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)]->[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
|
||||
@@ -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!
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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//
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
+41
-2
@@ -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
|
||||
+178
-178
@@ -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)
|
||||
+313
-313
@@ -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()
|
||||
..()
|
||||
|
||||
+550
-550
File diff suppressed because it is too large
Load Diff
+177
-177
@@ -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()
|
||||
+25
-25
@@ -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
|
||||
+3861
-3861
File diff suppressed because it is too large
Load Diff
+36
-36
@@ -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."
|
||||
+174
-174
@@ -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)
|
||||
+25
-25
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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.")
|
||||
@@ -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)
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
|
||||
updateicon()
|
||||
handle_regular_hud_updates()
|
||||
handle_vision()
|
||||
|
||||
if(ticker && ticker.mode)
|
||||
ticker.mode.check_win()
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user