+10
-1
@@ -11,7 +11,8 @@
|
||||
6. [Pull Request Process](#pull-request-process)
|
||||
7. [Porting features/sprites/sounds/tools from other codebases](#porting-featuresspritessoundstools-from-other-codebases)
|
||||
8. [Banned content](#banned-content)
|
||||
9. [A word on Git](#a-word-on-git)
|
||||
9. [Content requiring prior approval](#content-requiring-prior-approval)
|
||||
10. [A word on Git](#a-word-on-git)
|
||||
|
||||
## Reporting Issues
|
||||
If you ever encounter a bug in-game, the best way to let a coder know about it is with our GitHub Issue Tracker. Please make sure you use the supplied issue template, and include the round ID for the server.
|
||||
@@ -678,6 +679,14 @@ Do not add any of the following in a Pull Request or risk getting the PR closed:
|
||||
|
||||
Just because something isn't on this list doesn't mean that it's acceptable. Use common sense above all else.
|
||||
|
||||
## Content requiring prior approval
|
||||
Certain types of changes may require prior approval from maintainers. This currently includes:
|
||||
|
||||
* Code adding, removing, or updating the availability of alien races/species/human mutants. This includes pull requests attempting to add or remove features from said races/species/mutants. (Requires approval from at least one maintainer)
|
||||
* Code adding, removing, or modifying the functionality of adult-oriented features (such as, but not limited to: vore, genitals, MKUltra, and more). This also includes pull requests attempting to add or remove these features outright. (Requires approval from at least half of the formal maintainer team)
|
||||
|
||||
If a PR contains any of the above content, and it lacks prior approval, then it may closed at maintainer discretion. Prior approval requires an @Maintainer ping in a relevant development/code or staff channel on the Discord. This is primarily to limit the impact of PRs that're created in bad faith, or are otherwise counterproductive to the server's health.
|
||||
|
||||
## A word on Git
|
||||
This repository uses `LF` line endings for all code as specified in the **.gitattributes** and **.editorconfig** files.
|
||||
|
||||
|
||||
@@ -19118,6 +19118,10 @@
|
||||
/obj/effect/turf_decal/tile/yellow{
|
||||
dir = 4
|
||||
},
|
||||
/obj/machinery/navbeacon{
|
||||
codes_txt = "patrol;next_patrol=14-Starboard-Central";
|
||||
location = "13.2-Tcommstore"
|
||||
},
|
||||
/turf/open/floor/plasteel/dark/corner,
|
||||
/area/hallway/primary/starboard)
|
||||
"bxn" = (
|
||||
@@ -21190,10 +21194,6 @@
|
||||
/obj/structure/cable/yellow{
|
||||
icon_state = "1-2"
|
||||
},
|
||||
/obj/machinery/navbeacon{
|
||||
codes_txt = "patrol;next_patrol=14-Starboard-Central";
|
||||
location = "13.2-Tcommstore"
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/hallway/primary/starboard)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -182,7 +182,7 @@
|
||||
|
||||
////organ defines
|
||||
#define STANDARD_ORGAN_THRESHOLD 100
|
||||
#define STANDARD_ORGAN_HEALING (1/(15 MINUTES / (2 SECONDS)))
|
||||
#define STANDARD_ORGAN_HEALING (1/(15 MINUTES / (2 SECONDS))) / 3 //Base organ healing can be amped by a factor of up to x5 via satiety. This assumes it to be somewhat in the upper center of positive satiety as base.
|
||||
#define STANDARD_ORGAN_DECAY (1/(15 MINUTES / (2 SECONDS))) //designed to fail organs when left to decay for ~15 minutes. 2 SECOND is SSmobs tickrate.
|
||||
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@ GLOBAL_LIST_INIT(bitflags, list(
|
||||
#define OVERLAY_QUEUED_1 (1<<8)
|
||||
///Item has priority to check when entering or leaving.
|
||||
#define ON_BORDER_1 (1<<9)
|
||||
///Whether or not this atom shows screentips when hovered over
|
||||
#define NO_SCREENTIPS_1 (1<<10)
|
||||
///Prevent clicking things below it on the same turf eg. doors/ fulltile windows.
|
||||
#define PREVENT_CLICK_UNDER_1 (1<<11)
|
||||
#define HOLOGRAM_1 (1<<12)
|
||||
|
||||
@@ -57,6 +57,10 @@
|
||||
#define ADMIN_SET_SD_CODE "(<a href='?_src_=holder;[HrefToken(TRUE)];set_selfdestruct_code=1'>SETCODE</a>)"
|
||||
#define ADMIN_FULLMONTY_NONAME(user) "[ADMIN_QUE(user)] [ADMIN_PP(user)] [ADMIN_VV(user)] [ADMIN_SM(user)] [ADMIN_FLW(user)] [ADMIN_TP(user)] [ADMIN_INDIVIDUALLOG(user)] [ADMIN_SMITE(user)]"
|
||||
#define ADMIN_FULLMONTY(user) "[key_name_admin(user)] [ADMIN_FULLMONTY_NONAME(user)]"
|
||||
//ambition start
|
||||
#define ADMIN_TPMONTY_NONAME(user) "[ADMIN_QUE(user)] [ADMIN_JMP(user)] [ADMIN_FLW(user)]"
|
||||
#define ADMIN_TPMONTY(user) "[key_name_admin(user)] [ADMIN_TPMONTY_NONAME(user)]"
|
||||
//ambition end
|
||||
#define ADMIN_JMP(src) "(<a href='?_src_=holder;[HrefToken(TRUE)];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 AREACOORD(src) "[src ? "[get_area_name(src, TRUE)] ([src.x], [src.y], [src.z])" : "nonexistent location"]"
|
||||
|
||||
@@ -123,3 +123,9 @@ GLOBAL_LIST_EMPTY(living_heart_cache) //A list of all living hearts in existance
|
||||
|
||||
/// The dimensions of the antagonist preview icon. Will be scaled to this size.
|
||||
#define ANTAGONIST_PREVIEW_ICON_SIZE 96
|
||||
|
||||
//Objectives-Ambitions Panel
|
||||
#define REQUEST_NEW_OBJECTIVE "new_objective"
|
||||
#define REQUEST_DEL_OBJECTIVE "del_objective"
|
||||
#define REQUEST_WIN_OBJECTIVE "win_objective"
|
||||
#define REQUEST_LOSE_OBJECTIVE "lose_objective"
|
||||
|
||||
@@ -116,6 +116,7 @@
|
||||
#define GLOVES_MAX_TEMP_PROTECT 1500 //For some gloves
|
||||
#define SHOES_MIN_TEMP_PROTECT 2.0 //For gloves
|
||||
#define SHOES_MAX_TEMP_PROTECT 1500 //For gloves
|
||||
#define COAT_MAX_TEMP_PROTECT 330 //For winter coats (if they can stop you from getting cold why can't they do it the other way to a lesser extent)
|
||||
|
||||
#define PRESSURE_DAMAGE_COEFFICIENT 4 //The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE
|
||||
#define MAX_HIGH_PRESSURE_DAMAGE 16 // CITADEL CHANGES Max to 16, low to 8.
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
|
||||
//INDEXES
|
||||
#define COOLDOWN_EMPLOYMENT_CABINET "employment cabinet"
|
||||
#define COOLDOWN_AMBITION "ambition"
|
||||
#define COOLDOWN_OBJECTIVES "objectives"
|
||||
#define COOLDOWN_OBJ_ADMIN_PING "obj_admin_ping"
|
||||
|
||||
//car cooldowns
|
||||
#define COOLDOWN_CAR_HONK "car_honk"
|
||||
|
||||
@@ -359,6 +359,9 @@
|
||||
#define COMSIG_LIVING_RUN_BLOCK "living_do_run_block" //from base of mob/living/do_run_block(): (real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone)
|
||||
#define COMSIG_LIVING_GET_BLOCKING_ITEMS "get_blocking_items" //from base of mob/living/get_blocking_items(): (list/items)
|
||||
|
||||
#define COMSIG_LIVING_RESTING "living_on_resting" //from mob/living/set_resting
|
||||
#define COMSIG_LIVING_STOPPED_PULLING "living_on_stop_pulling" //from mob/living/stop_pulling
|
||||
|
||||
#define COMSIG_LIVING_ACTIVE_BLOCK_START "active_block_start" //from base of mob/living/keybind_start_active_blocking(): (obj/item/blocking_item, list/backup_items)
|
||||
#define COMPONENT_PREVENT_BLOCK_START 1
|
||||
#define COMSIG_LIVING_ACTIVE_PARRY_START "active_parry_start" //from base of mob/living/initiate_parry_sequence(): (parrying_method, datum/parrying_item_mob_or_art, list/backup_items, list/override)
|
||||
|
||||
+45
-80
@@ -6,87 +6,52 @@
|
||||
#define STORAGE_VIEW_DEPTH 2
|
||||
|
||||
//ITEM INVENTORY SLOT BITMASKS
|
||||
#define ITEM_SLOT_OCLOTHING (1<<0)
|
||||
#define ITEM_SLOT_ICLOTHING (1<<1)
|
||||
#define ITEM_SLOT_GLOVES (1<<2)
|
||||
#define ITEM_SLOT_EYES (1<<3)
|
||||
#define ITEM_SLOT_EARS (1<<4)
|
||||
#define ITEM_SLOT_MASK (1<<5)
|
||||
#define ITEM_SLOT_HEAD (1<<6)
|
||||
#define ITEM_SLOT_FEET (1<<7)
|
||||
#define ITEM_SLOT_ID (1<<8)
|
||||
#define ITEM_SLOT_BELT (1<<9)
|
||||
#define ITEM_SLOT_BACK (1<<10)
|
||||
#define ITEM_SLOT_POCKET (1<<11) // this is to allow items with a w_class of WEIGHT_CLASS_NORMAL or WEIGHT_CLASS_BULKY to fit in pockets.
|
||||
#define ITEM_SLOT_DENYPOCKET (1<<12) // this is to deny items with a w_class of WEIGHT_CLASS_SMALL or WEIGHT_CLASS_TINY to fit in pockets.
|
||||
#define ITEM_SLOT_NECK (1<<13)
|
||||
#define ITEM_SLOT_HANDS (1<<14)
|
||||
#define ITEM_SLOT_BACKPACK (1<<15)
|
||||
#define ITEM_SLOT_SUITSTORE (1<<16)
|
||||
/// Suit slot (armors, costumes, space suits, etc.)
|
||||
#define ITEM_SLOT_OCLOTHING (1<<0)
|
||||
/// Jumpsuit slot
|
||||
#define ITEM_SLOT_ICLOTHING (1<<1)
|
||||
/// Glove slot
|
||||
#define ITEM_SLOT_GLOVES (1<<2)
|
||||
/// Glasses slot
|
||||
#define ITEM_SLOT_EYES (1<<3)
|
||||
/// Ear slot (radios, earmuffs)
|
||||
#define ITEM_SLOT_EARS (1<<4)
|
||||
/// Mask slot
|
||||
#define ITEM_SLOT_MASK (1<<5)
|
||||
/// Head slot (helmets, hats, etc.)
|
||||
#define ITEM_SLOT_HEAD (1<<6)
|
||||
/// Shoe slot
|
||||
#define ITEM_SLOT_FEET (1<<7)
|
||||
/// ID slot
|
||||
#define ITEM_SLOT_ID (1<<8)
|
||||
/// Belt slot
|
||||
#define ITEM_SLOT_BELT (1<<9)
|
||||
/// Back slot
|
||||
#define ITEM_SLOT_BACK (1<<10)
|
||||
/// Dextrous simplemob "hands" (used for Drones and Dextrous Guardians)
|
||||
#define ITEM_SLOT_DEX_STORAGE (1<<11)
|
||||
/// Neck slot (ties, bedsheets, scarves)
|
||||
#define ITEM_SLOT_NECK (1<<12)
|
||||
/// A character's hand slots
|
||||
#define ITEM_SLOT_HANDS (1<<13)
|
||||
/// Inside of a character's backpack
|
||||
#define ITEM_SLOT_BACKPACK (1<<14)
|
||||
/// Suit Storage slot
|
||||
#define ITEM_SLOT_SUITSTORE (1<<15)
|
||||
/// Left Pocket slot
|
||||
#define ITEM_SLOT_LPOCKET (1<<16)
|
||||
/// Right Pocket slot
|
||||
#define ITEM_SLOT_RPOCKET (1<<17)
|
||||
/// Handcuff slot
|
||||
#define ITEM_SLOT_HANDCUFFED (1<<18)
|
||||
/// Legcuff slot (bolas, beartraps)
|
||||
#define ITEM_SLOT_LEGCUFFED (1<<19)
|
||||
|
||||
//SLOTS
|
||||
#define SLOT_BACK 1
|
||||
#define SLOT_WEAR_MASK 2
|
||||
#define SLOT_HANDCUFFED 3
|
||||
#define SLOT_HANDS 4 //wherever you provide a slot for hands you provide SLOT_HANDS
|
||||
//SLOT_HANDS as a slot will pick ANY available hand
|
||||
#define SLOT_BELT 5
|
||||
#define SLOT_WEAR_ID 6
|
||||
#define SLOT_EARS 7
|
||||
#define SLOT_GLASSES 8
|
||||
#define SLOT_GLOVES 9
|
||||
#define SLOT_NECK 10
|
||||
#define SLOT_HEAD 11
|
||||
#define SLOT_SHOES 12
|
||||
#define SLOT_WEAR_SUIT 13
|
||||
#define SLOT_W_UNIFORM 14
|
||||
#define SLOT_L_STORE 15
|
||||
#define SLOT_R_STORE 16
|
||||
#define SLOT_S_STORE 17
|
||||
#define SLOT_IN_BACKPACK 18
|
||||
#define SLOT_LEGCUFFED 19
|
||||
#define SLOT_GENERC_DEXTROUS_STORAGE 20
|
||||
|
||||
|
||||
#define SLOTS_AMT 20 // Keep this up to date!
|
||||
|
||||
//I hate that this has to exist
|
||||
/proc/slotdefine2slotbit(slotdefine) //Keep this up to date with the value of SLOT BITMASKS and SLOTS (the two define sections above)
|
||||
. = 0
|
||||
switch(slotdefine)
|
||||
if(SLOT_BACK)
|
||||
. = ITEM_SLOT_BACK
|
||||
if(SLOT_WEAR_MASK)
|
||||
. = ITEM_SLOT_MASK
|
||||
if(SLOT_NECK)
|
||||
. = ITEM_SLOT_NECK
|
||||
if(SLOT_BELT)
|
||||
. = ITEM_SLOT_BELT
|
||||
if(SLOT_WEAR_ID)
|
||||
. = ITEM_SLOT_ID
|
||||
if(SLOT_EARS)
|
||||
. = ITEM_SLOT_EARS
|
||||
if(SLOT_GLASSES)
|
||||
. = ITEM_SLOT_EYES
|
||||
if(SLOT_GLOVES)
|
||||
. = ITEM_SLOT_GLOVES
|
||||
if(SLOT_HEAD)
|
||||
. = ITEM_SLOT_HEAD
|
||||
if(SLOT_SHOES)
|
||||
. = ITEM_SLOT_FEET
|
||||
if(SLOT_WEAR_SUIT)
|
||||
. = ITEM_SLOT_OCLOTHING
|
||||
if(SLOT_W_UNIFORM)
|
||||
. = ITEM_SLOT_ICLOTHING
|
||||
if(SLOT_L_STORE, SLOT_R_STORE)
|
||||
. = ITEM_SLOT_POCKET
|
||||
if(SLOT_HANDS)
|
||||
. = ITEM_SLOT_HANDS
|
||||
if(SLOT_IN_BACKPACK)
|
||||
. = ITEM_SLOT_BACKPACK
|
||||
if(SLOT_S_STORE)
|
||||
. = ITEM_SLOT_SUITSTORE
|
||||
/// Total amount of slots
|
||||
#define SLOTS_AMT 20 // Keep this up to date!
|
||||
|
||||
//SLOT GROUP HELPERS
|
||||
#define ITEM_SLOT_POCKETS (ITEM_SLOT_LPOCKET|ITEM_SLOT_RPOCKET)
|
||||
|
||||
//Bit flags for the flags_inv variable, which determine when a piece of clothing hides another. IE a helmet hiding glasses.
|
||||
#define HIDEGLOVES (1<<0)
|
||||
@@ -245,4 +210,4 @@ GLOBAL_LIST_INIT(security_wintercoat_allowed, typecacheof(list(
|
||||
#define GET_INTERNAL_SLOTS(C) list(C.head, C.wear_mask)
|
||||
|
||||
//Slots that won't trigger humans' update_genitals() on equip().
|
||||
GLOBAL_LIST_INIT(no_genitals_update_slots, list(SLOT_L_STORE, SLOT_R_STORE, SLOT_S_STORE, SLOT_IN_BACKPACK, SLOT_LEGCUFFED, SLOT_HANDCUFFED, SLOT_HANDS, SLOT_GENERC_DEXTROUS_STORAGE))
|
||||
GLOBAL_LIST_INIT(no_genitals_update_slots, list(ITEM_SLOT_LPOCKET, ITEM_SLOT_RPOCKET, ITEM_SLOT_SUITSTORE, ITEM_SLOT_BACKPACK, ITEM_SLOT_LEGCUFFED, ITEM_SLOT_HANDCUFFED, ITEM_SLOT_HANDS, ITEM_SLOT_DEX_STORAGE))
|
||||
|
||||
@@ -76,7 +76,6 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
|
||||
#define isvampire(A) (is_species(A,/datum/species/vampire))
|
||||
#define isdullahan(A) (is_species(A, /datum/species/dullahan))
|
||||
|
||||
#define isangel(A) (is_species(A, /datum/species/angel))
|
||||
#define ismush(A) (is_species(A, /datum/species/mush))
|
||||
#define isshadow(A) (is_species(A, /datum/species/shadow))
|
||||
#define isrobotic(A) (is_species(A, /datum/species/ipc) || is_species(A, /datum/species/synthliz) || is_species(A, /datum/species/mammal/synthetic))
|
||||
|
||||
@@ -105,6 +105,9 @@
|
||||
|
||||
#define TORADIANS(degrees) ((degrees) * 0.0174532925)
|
||||
|
||||
/// Gets shift x that would be required the bitflag (1<<x)
|
||||
#define TOBITSHIFT(bit) ( log(2, bit) )
|
||||
|
||||
// Will filter out extra rotations and negative rotations
|
||||
// E.g: 540 becomes 180. -180 becomes 180.
|
||||
#define SIMPLIFY_DEGREES(degrees) (MODULUS((degrees), 360))
|
||||
|
||||
@@ -63,6 +63,9 @@
|
||||
|
||||
#define THRESHOLD_UNHUSK 50 // health threshold for synthflesh/rezadone to unhusk someone
|
||||
|
||||
#define SYNTHTISSUE_BORROW_CAP 250 //The cap for synthtissue's borrowed health value when used on someone dead or already having borrowed health.
|
||||
#define SYNTHTISSUE_DAMAGE_FLIP_CYCLES 45 //After how many cycles the damage will be pure toxdamage as opposed to clonedamage like initially. Gradually changes during its cycles.
|
||||
|
||||
//reagent bitflags, used for altering how they works
|
||||
#define REAGENT_DEAD_PROCESS (1<<0) //calls on_mob_dead() if present in a dead body
|
||||
#define REAGENT_DONOTSPLIT (1<<1) //Do not split the chem at all during processing
|
||||
|
||||
@@ -74,5 +74,5 @@
|
||||
)
|
||||
|
||||
#define BOMB_TARGET_POINTS 50000 //Adjust as needed. Actual hard cap is double this, but will never be reached due to hyperbolic curve.
|
||||
#define BOMB_TARGET_SIZE 200 // The shockwave radius required for a bomb to get TECHWEB_BOMB_MIDPOINT points.
|
||||
#define BOMB_SUB_TARGET_EXPONENT 2 // The power of the points curve below the target size. Higher = less points for worse bombs, below target.
|
||||
#define BOMB_TARGET_SIZE 175 // The shockwave radius required for a bomb to get TECHWEB_BOMB_MIDPOINT points.
|
||||
#define BOMB_SUB_TARGET_EXPONENT 3 // The power of the points curve below the target size. Higher = less points for worse bombs, below target.
|
||||
|
||||
@@ -86,6 +86,9 @@
|
||||
#define EMOTE_OMNI 4
|
||||
|
||||
//Don't set this very much higher then 1024 unless you like inviting people in to dos your server with message spam
|
||||
//ambition start
|
||||
#define MAX_AMBITION_LEN 1024
|
||||
//ambition end
|
||||
#define MAX_MESSAGE_LEN 4096 //Citadel edit: What's the WORST that could happen?
|
||||
#define MAX_FLAVOR_LEN 4096
|
||||
#define MAX_TASTE_LEN 40 //lick... vore... ew...
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#define SPECIES_ABDUCTOR "abductor"
|
||||
#define SPECIES_ANDROID "android"
|
||||
#define SPECIES_ANGEL "angel"
|
||||
#define SPECIES_MAMMAL "mammal"
|
||||
#define SPECIES_MAMMAL_SYNTHETIC "mammal_synthetic"
|
||||
#define SPECIES_ARACHNID "arachnid"
|
||||
@@ -53,3 +52,14 @@
|
||||
#define SPECIES_CATEGORY_SHADOW "shadow"
|
||||
#define SPECIES_CATEGORY_SKELETON "skeleton"
|
||||
#define SPECIES_CATEGORY_UNDEAD "undead"
|
||||
|
||||
|
||||
//Species Wing Type Defines ----------------------
|
||||
#define SPECIES_WINGS_ANGEL list("Angel")
|
||||
#define SPECIES_WINGS_DRAGON list("Dragon") //could also be considered demon wings or bat wings?
|
||||
#define SPECIES_WINGS_ROBOT list("Robotic")
|
||||
#define SPECIES_WINGS_INSECT list("Fly") //"hey when can we have something besides giant fly wings?" "when you sprite it!"
|
||||
#define SPECIES_WINGS_SKELETAL list("Skeleton")
|
||||
#define SPECIES_WINGS_MOTH list("Megamoth","Mothra")
|
||||
#define SPECIES_WINGS_JELLY list("Angel") //no actual slime wings present right now, but I'm making this in the event someone wants to sprite slime wings.
|
||||
#define SPECIES_WINGS_ALL list("Angel","Dragon","Robotic","Fly","Skeleton","Megamoth","Mothra") //keep this updated
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
#define HIGHEST_MEDIAN_VOTING "HIGHEST_MEDIAN"
|
||||
#define INSTANT_RUNOFF_VOTING "IRV"
|
||||
|
||||
#define VOTE_TRANSFER "Initiate Crew Transfer"
|
||||
#define VOTE_CONTINUE "Continue Playing"
|
||||
|
||||
#define SHOW_RESULTS (1<<0)
|
||||
#define SHOW_VOTES (1<<1)
|
||||
#define SHOW_WINNER (1<<2)
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
/*
|
||||
A Star pathfinding algorithm
|
||||
Returns a list of tiles forming a path from A to B, taking dense objects as well as walls, and the orientation of
|
||||
windows along the route into account.
|
||||
Use:
|
||||
your_list = AStar(start location, end location, moving atom, distance proc, max nodes, maximum node depth, minimum distance to target, adjacent proc, atom id, turfs to exclude, check only simulated)
|
||||
|
||||
Optional extras to add on (in order):
|
||||
Distance proc : the distance used in every A* calculation (length of path and heuristic)
|
||||
MaxNodes: The maximum number of nodes the returned path can be (0 = infinite)
|
||||
Maxnodedepth: The maximum number of nodes to search (default: 30, 0 = infinite)
|
||||
Mintargetdist: Minimum distance to the target before path returns, could be used to get
|
||||
near a target, but not right to it - for an AI mob with a gun, for example.
|
||||
Adjacent proc : returns the turfs to consider around the actually processed node
|
||||
Simulated only : whether to consider unsimulated turfs or not (used by some Adjacent proc)
|
||||
|
||||
Also added 'exclude' turf to avoid travelling over; defaults to null
|
||||
|
||||
Actual Adjacent procs :
|
||||
|
||||
/turf/proc/reachableAdjacentTurfs : returns reachable turfs in cardinal directions (uses simulated_only)
|
||||
|
||||
/turf/proc/reachableAdjacentAtmosTurfs : returns turfs in cardinal directions reachable via atmos
|
||||
|
||||
*/
|
||||
#define PF_TIEBREAKER 0.005
|
||||
//tiebreker weight.To help to choose between equal paths
|
||||
//////////////////////
|
||||
//datum/PathNode object
|
||||
//////////////////////
|
||||
#define MASK_ODD 85
|
||||
#define MASK_EVEN 170
|
||||
|
||||
|
||||
//A* nodes variables
|
||||
/datum/PathNode
|
||||
var/turf/source //turf associated with the PathNode
|
||||
var/datum/PathNode/prevNode //link to the parent PathNode
|
||||
var/f //A* Node weight (f = g + h)
|
||||
var/g //A* movement cost variable
|
||||
var/h //A* heuristic variable
|
||||
var/nt //count the number of Nodes traversed
|
||||
var/bf //bitflag for dir to expand.Some sufficiently advanced motherfuckery
|
||||
|
||||
/datum/PathNode/New(s,p,pg,ph,pnt,_bf)
|
||||
source = s
|
||||
prevNode = p
|
||||
g = pg
|
||||
h = ph
|
||||
f = g + h*(1+ PF_TIEBREAKER)
|
||||
nt = pnt
|
||||
bf = _bf
|
||||
|
||||
/datum/PathNode/proc/setp(p,pg,ph,pnt)
|
||||
prevNode = p
|
||||
g = pg
|
||||
h = ph
|
||||
f = g + h*(1+ PF_TIEBREAKER)
|
||||
nt = pnt
|
||||
|
||||
/datum/PathNode/proc/calc_f()
|
||||
f = g + h
|
||||
|
||||
//////////////////////
|
||||
//A* procs
|
||||
//////////////////////
|
||||
|
||||
//the weighting function, used in the A* algorithm
|
||||
/proc/PathWeightCompare(datum/PathNode/a, datum/PathNode/b)
|
||||
return a.f - b.f
|
||||
|
||||
//reversed so that the Heap is a MinHeap rather than a MaxHeap
|
||||
/proc/HeapPathWeightCompare(datum/PathNode/a, datum/PathNode/b)
|
||||
return b.f - a.f
|
||||
|
||||
//wrapper that returns an empty list if A* failed to find a path
|
||||
/proc/get_path_to(caller, end, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableTurftest, id=null, turf/exclude=null, simulated_only = 1)
|
||||
var/l = SSpathfinder.mobs.getfree(caller)
|
||||
while(!l)
|
||||
stoplag(3)
|
||||
l = SSpathfinder.mobs.getfree(caller)
|
||||
var/list/path = AStar(caller, end, dist, maxnodes, maxnodedepth, mintargetdist, adjacent,id, exclude, simulated_only)
|
||||
|
||||
SSpathfinder.mobs.found(l)
|
||||
if(!path)
|
||||
path = list()
|
||||
return path
|
||||
|
||||
/proc/cir_get_path_to(caller, end, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableTurftest, id=null, turf/exclude=null, simulated_only = 1)
|
||||
var/l = SSpathfinder.circuits.getfree(caller)
|
||||
while(!l)
|
||||
stoplag(3)
|
||||
l = SSpathfinder.circuits.getfree(caller)
|
||||
var/list/path = AStar(caller, end, dist, maxnodes, maxnodedepth, mintargetdist, adjacent,id, exclude, simulated_only)
|
||||
SSpathfinder.circuits.found(l)
|
||||
if(!path)
|
||||
path = list()
|
||||
return path
|
||||
|
||||
/proc/AStar(caller, _end, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableTurftest, id=null, turf/exclude=null, simulated_only = 1)
|
||||
//sanitation
|
||||
var/turf/end = get_turf(_end)
|
||||
var/turf/start = get_turf(caller)
|
||||
if(!start || !end)
|
||||
stack_trace("Invalid A* start or destination")
|
||||
return 0
|
||||
if( start.z != end.z || start == end ) //no pathfinding between z levels
|
||||
return 0
|
||||
if(maxnodes)
|
||||
//if start turf is farther than maxnodes from end turf, no need to do anything
|
||||
if(call(start, dist)(end) > maxnodes)
|
||||
return 0
|
||||
maxnodedepth = maxnodes //no need to consider path longer than maxnodes
|
||||
var/datum/Heap/open = new /datum/Heap(/proc/HeapPathWeightCompare) //the open list
|
||||
var/list/openc = new() //open list for node check
|
||||
var/list/path = null //the returned path, if any
|
||||
//initialization
|
||||
var/datum/PathNode/cur = new /datum/PathNode(start,null,0,call(start,dist)(end),0,15,1)//current processed turf
|
||||
open.Insert(cur)
|
||||
openc[start] = cur
|
||||
//then run the main loop
|
||||
while(!open.IsEmpty() && !path)
|
||||
cur = open.Pop() //get the lower f turf in the open list
|
||||
//get the lower f node on the open list
|
||||
//if we only want to get near the target, check if we're close enough
|
||||
var/closeenough
|
||||
if(mintargetdist)
|
||||
closeenough = call(cur.source,dist)(end) <= mintargetdist
|
||||
|
||||
|
||||
//found the target turf (or close enough), let's create the path to it
|
||||
if(cur.source == end || closeenough)
|
||||
path = new()
|
||||
path.Add(cur.source)
|
||||
while(cur.prevNode)
|
||||
cur = cur.prevNode
|
||||
path.Add(cur.source)
|
||||
break
|
||||
//get adjacents turfs using the adjacent proc, checking for access with id
|
||||
if((!maxnodedepth)||(cur.nt <= maxnodedepth))//if too many steps, don't process that path
|
||||
for(var/i = 0 to 3)
|
||||
var/f= 1<<i //get cardinal directions.1,2,4,8
|
||||
if(cur.bf & f)
|
||||
var/T = get_step(cur.source,f)
|
||||
if(T != exclude)
|
||||
var/datum/PathNode/CN = openc[T] //current checking turf
|
||||
var/r=((f & MASK_ODD)<<1)|((f & MASK_EVEN)>>1) //getting reverse direction throught swapping even and odd bits.((f & 01010101)<<1)|((f & 10101010)>>1)
|
||||
var/newg = cur.g + call(cur.source,dist)(T)
|
||||
if(CN)
|
||||
//is already in open list, check if it's a better way from the current turf
|
||||
CN.bf &= 15^r //we have no closed, so just cut off exceed dir.00001111 ^ reverse_dir.We don't need to expand to checked turf.
|
||||
if((newg < CN.g) )
|
||||
if(call(cur.source,adjacent)(caller, T, id, simulated_only))
|
||||
CN.setp(cur,newg,CN.h,cur.nt+1)
|
||||
open.ReSort(CN)//reorder the changed element in the list
|
||||
else
|
||||
//is not already in open list, so add it
|
||||
if(call(cur.source,adjacent)(caller, T, id, simulated_only))
|
||||
CN = new(T,cur,newg,call(T,dist)(end),cur.nt+1,15^r)
|
||||
open.Insert(CN)
|
||||
openc[T] = CN
|
||||
cur.bf = 0
|
||||
CHECK_TICK
|
||||
//reverse the path to get it from start to finish
|
||||
if(path)
|
||||
for(var/i = 1 to round(0.5*path.len))
|
||||
path.Swap(i,path.len-i+1)
|
||||
openc = null
|
||||
//cleaning after us
|
||||
return path
|
||||
|
||||
//Returns adjacent turfs in cardinal directions that are reachable
|
||||
//simulated_only controls whether only simulated turfs are considered or not
|
||||
|
||||
/turf/proc/reachableAdjacentTurfs(caller, ID, simulated_only)
|
||||
var/list/L = new()
|
||||
var/turf/T
|
||||
var/static/space_type_cache = typecacheof(/turf/open/space)
|
||||
|
||||
for(var/k in 1 to GLOB.cardinals.len)
|
||||
T = get_step(src,GLOB.cardinals[k])
|
||||
if(!T || (simulated_only && space_type_cache[T.type]))
|
||||
continue
|
||||
if(!T.density && !LinkBlockedWithAccess(T,caller, ID))
|
||||
L.Add(T)
|
||||
return L
|
||||
|
||||
/turf/proc/reachableTurftest(caller, var/turf/T, ID, simulated_only)
|
||||
if(T && !T.density && !(simulated_only && SSpathfinder.space_type_cache[T.type]) && !LinkBlockedWithAccess(T,caller, ID))
|
||||
return TRUE
|
||||
|
||||
//Returns adjacent turfs in cardinal directions that are reachable via atmos
|
||||
/turf/proc/reachableAdjacentAtmosTurfs()
|
||||
return atmos_adjacent_turfs
|
||||
|
||||
/turf/proc/LinkBlockedWithAccess(turf/T, caller, ID)
|
||||
var/adir = get_dir(src, T)
|
||||
var/rdir = ((adir & MASK_ODD)<<1)|((adir & MASK_EVEN)>>1)
|
||||
for(var/obj/structure/window/W in src)
|
||||
if(!W.CanAStarPass(ID, adir))
|
||||
return 1
|
||||
for(var/obj/machinery/door/window/W in src)
|
||||
if(!W.CanAStarPass(ID, adir))
|
||||
return 1
|
||||
for(var/obj/O in T)
|
||||
if(!O.CanAStarPass(ID, rdir, caller))
|
||||
return 1
|
||||
|
||||
return 0
|
||||
@@ -14,6 +14,9 @@
|
||||
///Like LAZYCOPY - copies an input list if the list has entries, If it doesn't the assigned list is nulled
|
||||
#define LAZYLISTDUPLICATE(L) (L ? L.Copy() : null )
|
||||
#define LAZYREMOVE(L, I) if(L) { L -= I; if(!length(L)) { L = null; } }
|
||||
//ambition start
|
||||
#define LAZYCUT(L, S, E) if((length(L) >= S) && (E == 0 || length(L) >= (E - 1))) { L.Cut(S, E); if(!length(L)) { L = null; } }
|
||||
//ambition end
|
||||
#define LAZYADD(L, I) if(!L) { L = list(); } L += I;
|
||||
#define LAZYOR(L, I) if(!L) { L = list(); } L |= I;
|
||||
#define LAZYFIND(L, V) (L ? L.Find(V) : 0)
|
||||
|
||||
@@ -109,6 +109,10 @@
|
||||
if (CONFIG_GET(flag/log_attack))
|
||||
WRITE_LOG(GLOB.world_attack_log, "ATTACK: [text]")
|
||||
|
||||
/proc/log_victim(text)
|
||||
if (CONFIG_GET(flag/log_victim))
|
||||
WRITE_LOG(GLOB.world_victim_log, "VICTIM: [text]")
|
||||
|
||||
/proc/log_manifest(ckey, datum/mind/mind,mob/body, latejoin = FALSE)
|
||||
if (CONFIG_GET(flag/log_manifest))
|
||||
WRITE_LOG(GLOB.world_manifest_log, "[ckey] \\ [body.real_name] \\ [mind.assigned_role] \\ [mind.special_role ? mind.special_role : "NONE"] \\ [latejoin ? "LATEJOIN":"ROUNDSTART"]")
|
||||
|
||||
@@ -140,3 +140,6 @@ GLOBAL_VAR_INIT(cmp_field, "name")
|
||||
|
||||
/proc/cmp_typepaths_asc(A, B)
|
||||
return sorttext("[B]","[A]")
|
||||
|
||||
/proc/cmp_playtime(list/A, list/B)
|
||||
return A["playtime"] - B["playtime"]
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
if(length(inhand_equipment))
|
||||
for(var/path in inhand_equipment)
|
||||
var/obj/item/I = new path
|
||||
mannequin.equip_to_slot_if_possible(I, SLOT_HANDS, TRUE, TRUE, TRUE, TRUE)
|
||||
mannequin.equip_to_slot_if_possible(I, ITEM_SLOT_HANDS, TRUE, TRUE, TRUE, TRUE)
|
||||
|
||||
|
||||
var/icon/combined = new
|
||||
|
||||
+32
-27
@@ -1,39 +1,45 @@
|
||||
|
||||
//////////////////////
|
||||
//datum/Heap object
|
||||
//datum/heap object
|
||||
//////////////////////
|
||||
|
||||
/datum/Heap
|
||||
/datum/heap
|
||||
var/list/L
|
||||
var/cmp
|
||||
|
||||
/datum/Heap/New(compare)
|
||||
/datum/heap/New(compare)
|
||||
L = new()
|
||||
cmp = compare
|
||||
|
||||
/datum/Heap/proc/IsEmpty()
|
||||
return !L.len
|
||||
/datum/heap/Destroy(force, ...)
|
||||
for(var/i in L) // because this is before the list helpers are loaded
|
||||
qdel(i)
|
||||
L = null
|
||||
return ..()
|
||||
|
||||
//Insert and place at its position a new node in the heap
|
||||
/datum/Heap/proc/Insert(atom/A)
|
||||
/datum/heap/proc/is_empty()
|
||||
return !length(L)
|
||||
|
||||
//insert and place at its position a new node in the heap
|
||||
/datum/heap/proc/insert(atom/A)
|
||||
|
||||
L.Add(A)
|
||||
Swim(L.len)
|
||||
swim(length(L))
|
||||
|
||||
//removes and returns the first element of the heap
|
||||
//(i.e the max or the min dependant on the comparison function)
|
||||
/datum/Heap/proc/Pop()
|
||||
if(!L.len)
|
||||
/datum/heap/proc/pop()
|
||||
if(!length(L))
|
||||
return 0
|
||||
. = L[1]
|
||||
|
||||
L[1] = L[L.len]
|
||||
L.Cut(L.len)
|
||||
if(L.len)
|
||||
Sink(1)
|
||||
L[1] = L[length(L)]
|
||||
L.Cut(length(L))
|
||||
if(length(L))
|
||||
sink(1)
|
||||
|
||||
|
||||
//Get a node up to its right position in the heap
|
||||
/datum/Heap/proc/Swim(var/index)
|
||||
/datum/heap/proc/swim(index)
|
||||
var/parent = round(index * 0.5)
|
||||
|
||||
while(parent > 0 && (call(cmp)(L[index],L[parent]) > 0))
|
||||
@@ -42,21 +48,21 @@
|
||||
parent = round(index * 0.5)
|
||||
|
||||
//Get a node down to its right position in the heap
|
||||
/datum/Heap/proc/Sink(var/index)
|
||||
var/g_child = GetGreaterChild(index)
|
||||
/datum/heap/proc/sink(index)
|
||||
var/g_child = get_greater_child(index)
|
||||
|
||||
while(g_child > 0 && (call(cmp)(L[index],L[g_child]) < 0))
|
||||
L.Swap(index,g_child)
|
||||
index = g_child
|
||||
g_child = GetGreaterChild(index)
|
||||
g_child = get_greater_child(index)
|
||||
|
||||
//Returns the greater (relative to the comparison proc) of a node children
|
||||
//or 0 if there's no child
|
||||
/datum/Heap/proc/GetGreaterChild(var/index)
|
||||
if(index * 2 > L.len)
|
||||
/datum/heap/proc/get_greater_child(index)
|
||||
if(index * 2 > length(L))
|
||||
return 0
|
||||
|
||||
if(index * 2 + 1 > L.len)
|
||||
if(index * 2 + 1 > length(L))
|
||||
return index * 2
|
||||
|
||||
if(call(cmp)(L[index * 2],L[index * 2 + 1]) < 0)
|
||||
@@ -65,12 +71,11 @@
|
||||
return index * 2
|
||||
|
||||
//Replaces a given node so it verify the heap condition
|
||||
/datum/Heap/proc/ReSort(atom/A)
|
||||
/datum/heap/proc/resort(atom/A)
|
||||
var/index = L.Find(A)
|
||||
|
||||
Swim(index)
|
||||
Sink(index)
|
||||
swim(index)
|
||||
sink(index)
|
||||
|
||||
/datum/Heap/proc/List()
|
||||
/datum/heap/proc/List()
|
||||
. = L.Copy()
|
||||
|
||||
|
||||
@@ -0,0 +1,359 @@
|
||||
/**
|
||||
* This file contains the stuff you need for using JPS (Jump Point Search) pathing, an alternative to A* that skips
|
||||
* over large numbers of uninteresting tiles resulting in much quicker pathfinding solutions. Mind that diagonals
|
||||
* cost the same as cardinal moves currently, so paths may look a bit strange, but should still be optimal.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is the proc you use whenever you want to have pathfinding more complex than "try stepping towards the thing".
|
||||
* If no path was found, returns an empty list, which is important for bots like medibots who expect an empty list rather than nothing.
|
||||
*
|
||||
* Arguments:
|
||||
* * caller: The movable atom that's trying to find the path
|
||||
* * end: What we're trying to path to. It doesn't matter if this is a turf or some other atom, we're gonna just path to the turf it's on anyway
|
||||
* * max_distance: The maximum number of steps we can take in a given path to search (default: 30, 0 = infinite)
|
||||
* * mintargetdistance: Minimum distance to the target before path returns, could be used to get near a target, but not right to it - for an AI mob with a gun, for example.
|
||||
* * id: An ID card representing what access we have and what doors we can open. Its location relative to the pathing atom is irrelevant
|
||||
* * simulated_only: Whether we consider turfs without atmos simulation (AKA do we want to ignore space)
|
||||
* * exclude: If we want to avoid a specific turf, like if we're a mulebot who already got blocked by some turf
|
||||
* * skip_first: Whether or not to delete the first item in the path. This would be done because the first item is the starting tile, which can break movement for some creatures.
|
||||
*/
|
||||
/proc/get_path_to(caller, end, max_distance = 30, mintargetdist, id=null, simulated_only = TRUE, turf/exclude, skip_first=TRUE)
|
||||
if(!caller || !get_turf(end))
|
||||
return
|
||||
|
||||
var/l = SSpathfinder.mobs.getfree(caller)
|
||||
while(!l)
|
||||
stoplag(3)
|
||||
l = SSpathfinder.mobs.getfree(caller)
|
||||
|
||||
var/list/path
|
||||
var/datum/pathfind/pathfind_datum = new(caller, end, id, max_distance, mintargetdist, simulated_only, exclude)
|
||||
path = pathfind_datum.search()
|
||||
qdel(pathfind_datum)
|
||||
|
||||
SSpathfinder.mobs.found(l)
|
||||
if(!path)
|
||||
path = list()
|
||||
if(length(path) > 0 && skip_first)
|
||||
path.Cut(1,2)
|
||||
return path
|
||||
|
||||
/**
|
||||
* A helper macro to see if it's possible to step from the first turf into the second one, minding things like door access and directional windows.
|
||||
* Note that this can only be used inside the [datum/pathfind][pathfind datum] since it uses variables from said datum.
|
||||
* If you really want to optimize things, optimize this, cuz this gets called a lot.
|
||||
*/
|
||||
#define CAN_STEP(cur_turf, next) (next && !next.density && cur_turf.Adjacent(next) && !(simulated_only && SSpathfinder.space_type_cache[next.type]) && !cur_turf.LinkBlockedWithAccess(next,caller, id) && (next != avoid))
|
||||
/// Another helper macro for JPS, for telling when a node has forced neighbors that need expanding
|
||||
#define STEP_NOT_HERE_BUT_THERE(cur_turf, dirA, dirB) ((!CAN_STEP(cur_turf, get_step(cur_turf, dirA)) && CAN_STEP(cur_turf, get_step(cur_turf, dirB))))
|
||||
|
||||
/// The JPS Node datum represents a turf that we find interesting enough to add to the open list and possibly search for new tiles from
|
||||
/datum/jps_node
|
||||
/// The turf associated with this node
|
||||
var/turf/tile
|
||||
/// The node we just came from
|
||||
var/datum/jps_node/previous_node
|
||||
/// The A* node weight (f_value = number_of_tiles + heuristic)
|
||||
var/f_value
|
||||
/// The A* node heuristic (a rough estimate of how far we are from the goal)
|
||||
var/heuristic
|
||||
/// How many steps it's taken to get here from the start (currently pulling double duty as steps taken & cost to get here, since all moves incl diagonals cost 1 rn)
|
||||
var/number_tiles
|
||||
/// How many steps it took to get here from the last node
|
||||
var/jumps
|
||||
/// Nodes store the endgoal so they can process their heuristic without a reference to the pathfind datum
|
||||
var/turf/node_goal
|
||||
|
||||
/datum/jps_node/New(turf/our_tile, datum/jps_node/incoming_previous_node, jumps_taken, turf/incoming_goal)
|
||||
tile = our_tile
|
||||
jumps = jumps_taken
|
||||
if(incoming_goal) // if we have the goal argument, this must be the first/starting node
|
||||
node_goal = incoming_goal
|
||||
else if(incoming_previous_node) // if we have the parent, this is from a direct lateral/diagonal scan, we can fill it all out now
|
||||
previous_node = incoming_previous_node
|
||||
number_tiles = previous_node.number_tiles + jumps
|
||||
node_goal = previous_node.node_goal
|
||||
heuristic = get_dist(tile, node_goal)
|
||||
f_value = number_tiles + heuristic
|
||||
// otherwise, no parent node means this is from a subscan lateral scan, so we just need the tile for now until we call [datum/jps/proc/update_parent] on it
|
||||
|
||||
/datum/jps_node/Destroy(force, ...)
|
||||
previous_node = null
|
||||
return ..()
|
||||
|
||||
/datum/jps_node/proc/update_parent(datum/jps_node/new_parent)
|
||||
previous_node = new_parent
|
||||
node_goal = previous_node.node_goal
|
||||
jumps = get_dist(tile, previous_node.tile)
|
||||
number_tiles = previous_node.number_tiles + jumps
|
||||
heuristic = get_dist(tile, node_goal)
|
||||
f_value = number_tiles + heuristic
|
||||
|
||||
/// TODO: Macro this to reduce proc overhead
|
||||
/proc/HeapPathWeightCompare(datum/jps_node/a, datum/jps_node/b)
|
||||
return b.f_value - a.f_value
|
||||
|
||||
/// The datum used to handle the JPS pathfinding, completely self-contained
|
||||
/datum/pathfind
|
||||
/// The thing that we're actually trying to path for
|
||||
var/atom/movable/caller
|
||||
/// The turf where we started at
|
||||
var/turf/start
|
||||
/// The turf we're trying to path to (note that this won't track a moving target)
|
||||
var/turf/end
|
||||
/// The open list/stack we pop nodes out from (TODO: make this a normal list and macro-ize the heap operations to reduce proc overhead)
|
||||
var/datum/heap/open
|
||||
///An assoc list that serves as the closed list & tracks what turfs came from where. Key is the turf, and the value is what turf it came from
|
||||
var/list/sources
|
||||
/// The list we compile at the end if successful to pass back
|
||||
var/list/path
|
||||
|
||||
// general pathfinding vars/args
|
||||
/// An ID card representing what access we have and what doors we can open. Its location relative to the pathing atom is irrelevant
|
||||
var/obj/item/card/id/id
|
||||
/// How far away we have to get to the end target before we can call it quits
|
||||
var/mintargetdist = 0
|
||||
/// I don't know what this does vs , but they limit how far we can search before giving up on a path
|
||||
var/max_distance = 30
|
||||
/// Space is big and empty, if this is TRUE then we ignore pathing through unsimulated tiles
|
||||
var/simulated_only
|
||||
/// A specific turf we're avoiding, like if a mulebot is being blocked by someone t-posing in a doorway we're trying to get through
|
||||
var/turf/avoid
|
||||
|
||||
/datum/pathfind/New(atom/movable/caller, atom/goal, id, max_distance, mintargetdist, simulated_only, avoid)
|
||||
src.caller = caller
|
||||
end = get_turf(goal)
|
||||
open = new /datum/heap(/proc/HeapPathWeightCompare)
|
||||
sources = new()
|
||||
src.id = id
|
||||
src.max_distance = max_distance
|
||||
src.mintargetdist = mintargetdist
|
||||
src.simulated_only = simulated_only
|
||||
src.avoid = avoid
|
||||
|
||||
/**
|
||||
* search() is the proc you call to kick off and handle the actual pathfinding, and kills the pathfind datum instance when it's done.
|
||||
*
|
||||
* If a valid path was found, it's returned as a list. If invalid or cross-z-level params are entered, or if there's no valid path found, we
|
||||
* return null, which [/proc/get_path_to] translates to an empty list (notable for simple bots, who need empty lists)
|
||||
*/
|
||||
/datum/pathfind/proc/search()
|
||||
start = get_turf(caller)
|
||||
if(!start || !end)
|
||||
stack_trace("Invalid A* start or destination")
|
||||
return
|
||||
if(start.z != end.z || start == end ) //no pathfinding between z levels
|
||||
return
|
||||
if(max_distance && (max_distance < get_dist(start, end))) //if start turf is farther than max_distance from end turf, no need to do anything
|
||||
return
|
||||
|
||||
//initialization
|
||||
var/datum/jps_node/current_processed_node = new (start, -1, 0, end)
|
||||
open.insert(current_processed_node)
|
||||
sources[start] = start // i'm sure this is fine
|
||||
|
||||
//then run the main loop
|
||||
while(!open.is_empty() && !path)
|
||||
if(!caller)
|
||||
return
|
||||
current_processed_node = open.pop() //get the lower f_value turf in the open list
|
||||
if(max_distance && (current_processed_node.number_tiles > max_distance))//if too many steps, don't process that path
|
||||
continue
|
||||
|
||||
var/turf/current_turf = current_processed_node.tile
|
||||
for(var/scan_direction in list(EAST, WEST, NORTH, SOUTH))
|
||||
lateral_scan_spec(current_turf, scan_direction, current_processed_node)
|
||||
|
||||
for(var/scan_direction in list(NORTHEAST, SOUTHEAST, NORTHWEST, SOUTHWEST))
|
||||
diag_scan_spec(current_turf, scan_direction, current_processed_node)
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//we're done! reverse the path to get it from start to finish
|
||||
if(path)
|
||||
for(var/i = 1 to round(0.5 * length(path)))
|
||||
path.Swap(i, length(path) - i + 1)
|
||||
|
||||
sources = null
|
||||
qdel(open)
|
||||
return path
|
||||
|
||||
/// Called when we've hit the goal with the node that represents the last tile, then sets the path var to that path so it can be returned by [datum/pathfind/proc/search]
|
||||
/datum/pathfind/proc/unwind_path(datum/jps_node/unwind_node)
|
||||
path = new()
|
||||
var/turf/iter_turf = unwind_node.tile
|
||||
path.Add(iter_turf)
|
||||
|
||||
while(unwind_node.previous_node)
|
||||
var/dir_goal = get_dir(iter_turf, unwind_node.previous_node.tile)
|
||||
for(var/i = 1 to unwind_node.jumps)
|
||||
iter_turf = get_step(iter_turf,dir_goal)
|
||||
path.Add(iter_turf)
|
||||
unwind_node = unwind_node.previous_node
|
||||
|
||||
/**
|
||||
* For performing lateral scans from a given starting turf.
|
||||
*
|
||||
* These scans are called from both the main search loop, as well as subscans for diagonal scans, and they treat finding interesting turfs slightly differently.
|
||||
* If we're doing a normal lateral scan, we already have a parent node supplied, so we just create the new node and immediately insert it into the heap, ezpz.
|
||||
* If we're part of a subscan, we still need for the diagonal scan to generate a parent node, so we return a node datum with just the turf and let the diag scan
|
||||
* proc handle transferring the values and inserting them into the heap.
|
||||
*
|
||||
* Arguments:
|
||||
* * original_turf: What turf did we start this scan at?
|
||||
* * heading: What direction are we going in? Obviously, should be cardinal
|
||||
* * parent_node: Only given for normal lateral scans, if we don't have one, we're a diagonal subscan.
|
||||
*/
|
||||
/datum/pathfind/proc/lateral_scan_spec(turf/original_turf, heading, datum/jps_node/parent_node)
|
||||
var/steps_taken = 0
|
||||
|
||||
var/turf/current_turf = original_turf
|
||||
var/turf/lag_turf = original_turf
|
||||
|
||||
while(TRUE)
|
||||
if(path)
|
||||
return
|
||||
lag_turf = current_turf
|
||||
current_turf = get_step(current_turf, heading)
|
||||
steps_taken++
|
||||
if(!CAN_STEP(lag_turf, current_turf))
|
||||
return
|
||||
|
||||
if(current_turf == end || (mintargetdist && (get_dist(current_turf, end) <= mintargetdist)))
|
||||
var/datum/jps_node/final_node = new(current_turf, parent_node, steps_taken)
|
||||
sources[current_turf] = original_turf
|
||||
if(parent_node) // if this is a direct lateral scan we can wrap up, if it's a subscan from a diag, we need to let the diag make their node first, then finish
|
||||
unwind_path(final_node)
|
||||
return final_node
|
||||
else if(sources[current_turf]) // already visited, essentially in the closed list
|
||||
return
|
||||
else
|
||||
sources[current_turf] = original_turf
|
||||
|
||||
if(parent_node && parent_node.number_tiles + steps_taken > max_distance)
|
||||
return
|
||||
|
||||
var/interesting = FALSE // have we found a forced neighbor that would make us add this turf to the open list?
|
||||
|
||||
switch(heading)
|
||||
if(NORTH)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, WEST, NORTHWEST) || STEP_NOT_HERE_BUT_THERE(current_turf, EAST, NORTHEAST))
|
||||
interesting = TRUE
|
||||
if(SOUTH)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, WEST, SOUTHWEST) || STEP_NOT_HERE_BUT_THERE(current_turf, EAST, SOUTHEAST))
|
||||
interesting = TRUE
|
||||
if(EAST)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, NORTH, NORTHEAST) || STEP_NOT_HERE_BUT_THERE(current_turf, SOUTH, SOUTHEAST))
|
||||
interesting = TRUE
|
||||
if(WEST)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, NORTH, NORTHWEST) || STEP_NOT_HERE_BUT_THERE(current_turf, SOUTH, SOUTHWEST))
|
||||
interesting = TRUE
|
||||
|
||||
if(interesting)
|
||||
var/datum/jps_node/newnode = new(current_turf, parent_node, steps_taken)
|
||||
if(parent_node) // if we're a diagonal subscan, we'll handle adding ourselves to the heap in the diag
|
||||
open.insert(newnode)
|
||||
return newnode
|
||||
|
||||
/**
|
||||
* For performing diagonal scans from a given starting turf.
|
||||
*
|
||||
* Unlike lateral scans, these only are called from the main search loop, so we don't need to worry about returning anything,
|
||||
* though we do need to handle the return values of our lateral subscans of course.
|
||||
*
|
||||
* Arguments:
|
||||
* * original_turf: What turf did we start this scan at?
|
||||
* * heading: What direction are we going in? Obviously, should be diagonal
|
||||
* * parent_node: We should always have a parent node for diagonals
|
||||
*/
|
||||
/datum/pathfind/proc/diag_scan_spec(turf/original_turf, heading, datum/jps_node/parent_node)
|
||||
var/steps_taken = 0
|
||||
var/turf/current_turf = original_turf
|
||||
var/turf/lag_turf = original_turf
|
||||
|
||||
while(TRUE)
|
||||
if(path)
|
||||
return
|
||||
lag_turf = current_turf
|
||||
current_turf = get_step(current_turf, heading)
|
||||
steps_taken++
|
||||
if(!CAN_STEP(lag_turf, current_turf))
|
||||
return
|
||||
|
||||
if(current_turf == end || (mintargetdist && (get_dist(current_turf, end) <= mintargetdist)))
|
||||
var/datum/jps_node/final_node = new(current_turf, parent_node, steps_taken)
|
||||
sources[current_turf] = original_turf
|
||||
unwind_path(final_node)
|
||||
return
|
||||
else if(sources[current_turf]) // already visited, essentially in the closed list
|
||||
return
|
||||
else
|
||||
sources[current_turf] = original_turf
|
||||
|
||||
if(parent_node.number_tiles + steps_taken > max_distance)
|
||||
return
|
||||
|
||||
var/interesting = FALSE // have we found a forced neighbor that would make us add this turf to the open list?
|
||||
var/datum/jps_node/possible_child_node // otherwise, did one of our lateral subscans turn up something?
|
||||
|
||||
switch(heading)
|
||||
if(NORTHWEST)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, EAST, NORTHEAST) || STEP_NOT_HERE_BUT_THERE(current_turf, SOUTH, SOUTHWEST))
|
||||
interesting = TRUE
|
||||
else
|
||||
possible_child_node = (lateral_scan_spec(current_turf, WEST) || lateral_scan_spec(current_turf, NORTH))
|
||||
if(NORTHEAST)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, WEST, NORTHWEST) || STEP_NOT_HERE_BUT_THERE(current_turf, SOUTH, SOUTHEAST))
|
||||
interesting = TRUE
|
||||
else
|
||||
possible_child_node = (lateral_scan_spec(current_turf, EAST) || lateral_scan_spec(current_turf, NORTH))
|
||||
if(SOUTHWEST)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, EAST, SOUTHEAST) || STEP_NOT_HERE_BUT_THERE(current_turf, NORTH, NORTHWEST))
|
||||
interesting = TRUE
|
||||
else
|
||||
possible_child_node = (lateral_scan_spec(current_turf, SOUTH) || lateral_scan_spec(current_turf, WEST))
|
||||
if(SOUTHEAST)
|
||||
if(STEP_NOT_HERE_BUT_THERE(current_turf, WEST, SOUTHWEST) || STEP_NOT_HERE_BUT_THERE(current_turf, NORTH, NORTHEAST))
|
||||
interesting = TRUE
|
||||
else
|
||||
possible_child_node = (lateral_scan_spec(current_turf, SOUTH) || lateral_scan_spec(current_turf, EAST))
|
||||
|
||||
if(interesting || possible_child_node)
|
||||
var/datum/jps_node/newnode = new(current_turf, parent_node, steps_taken)
|
||||
open.insert(newnode)
|
||||
if(possible_child_node)
|
||||
possible_child_node.update_parent(newnode)
|
||||
open.insert(possible_child_node)
|
||||
if(possible_child_node.tile == end || (mintargetdist && (get_dist(possible_child_node.tile, end) <= mintargetdist)))
|
||||
unwind_path(possible_child_node)
|
||||
return
|
||||
|
||||
/**
|
||||
* For seeing if we can actually move between 2 given turfs while accounting for our access and the caller's pass_flags
|
||||
*
|
||||
* Arguments:
|
||||
* * caller: The movable, if one exists, being used for mobility checks to see what tiles it can reach
|
||||
* * ID: An ID card that decides if we can gain access to doors that would otherwise block a turf
|
||||
* * simulated_only: Do we only worry about turfs with simulated atmos, most notably things that aren't space?
|
||||
*/
|
||||
/turf/proc/LinkBlockedWithAccess(turf/destination_turf, caller, ID)
|
||||
var/actual_dir = get_dir(src, destination_turf)
|
||||
|
||||
for(var/obj/structure/window/iter_window in src)
|
||||
if(!iter_window.CanAStarPass(ID, actual_dir))
|
||||
return TRUE
|
||||
|
||||
for(var/obj/machinery/door/window/iter_windoor in src)
|
||||
if(!iter_windoor.CanAStarPass(ID, actual_dir))
|
||||
return TRUE
|
||||
|
||||
var/reverse_dir = get_dir(destination_turf, src)
|
||||
for(var/obj/iter_object in destination_turf)
|
||||
if(!iter_object.CanAStarPass(ID, reverse_dir, caller))
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
#undef CAN_STEP
|
||||
#undef STEP_NOT_HERE_BUT_THERE
|
||||
@@ -203,62 +203,62 @@
|
||||
/mob/living/carbon/human/p_they(capitalized, temp_gender)
|
||||
var/list/obscured = check_obscured_slots()
|
||||
var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
|
||||
if((SLOT_W_UNIFORM in obscured) && skipface)
|
||||
if((ITEM_SLOT_ICLOTHING in obscured) && skipface)
|
||||
temp_gender = PLURAL
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/p_their(capitalized, temp_gender)
|
||||
var/list/obscured = check_obscured_slots()
|
||||
var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
|
||||
if((SLOT_W_UNIFORM in obscured) && skipface)
|
||||
if((ITEM_SLOT_ICLOTHING in obscured) && skipface)
|
||||
temp_gender = PLURAL
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/p_them(capitalized, temp_gender)
|
||||
var/list/obscured = check_obscured_slots()
|
||||
var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
|
||||
if((SLOT_W_UNIFORM in obscured) && skipface)
|
||||
if((ITEM_SLOT_ICLOTHING in obscured) && skipface)
|
||||
temp_gender = PLURAL
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/p_have(temp_gender)
|
||||
var/list/obscured = check_obscured_slots()
|
||||
var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
|
||||
if((SLOT_W_UNIFORM in obscured) && skipface)
|
||||
if((ITEM_SLOT_ICLOTHING in obscured) && skipface)
|
||||
temp_gender = PLURAL
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/p_are(temp_gender)
|
||||
var/list/obscured = check_obscured_slots()
|
||||
var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
|
||||
if((SLOT_W_UNIFORM in obscured) && skipface)
|
||||
if((ITEM_SLOT_ICLOTHING in obscured) && skipface)
|
||||
temp_gender = PLURAL
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/p_were(temp_gender)
|
||||
var/list/obscured = check_obscured_slots()
|
||||
var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
|
||||
if((SLOT_W_UNIFORM in obscured) && skipface)
|
||||
if((ITEM_SLOT_ICLOTHING in obscured) && skipface)
|
||||
temp_gender = PLURAL
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/p_do(temp_gender)
|
||||
var/list/obscured = check_obscured_slots()
|
||||
var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
|
||||
if((SLOT_W_UNIFORM in obscured) && skipface)
|
||||
if((ITEM_SLOT_ICLOTHING in obscured) && skipface)
|
||||
temp_gender = PLURAL
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/p_s(temp_gender)
|
||||
var/list/obscured = check_obscured_slots()
|
||||
var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
|
||||
if((SLOT_W_UNIFORM in obscured) && skipface)
|
||||
if((ITEM_SLOT_ICLOTHING in obscured) && skipface)
|
||||
temp_gender = PLURAL
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/p_es(temp_gender)
|
||||
var/list/obscured = check_obscured_slots()
|
||||
var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
|
||||
if((SLOT_W_UNIFORM in obscured) && skipface)
|
||||
if((ITEM_SLOT_ICLOTHING in obscured) && skipface)
|
||||
temp_gender = PLURAL
|
||||
return ..()
|
||||
|
||||
@@ -624,6 +624,10 @@
|
||||
currrent_category = A.roundend_category
|
||||
previous_category = A
|
||||
result += A.roundend_report()
|
||||
//ambition start
|
||||
for(var/count in 1 to LAZYLEN(A.owner.ambitions))
|
||||
result += "<br><B>Ambition #[count]</B>: [A.owner.ambitions[count]]"
|
||||
//ambition end
|
||||
result += "<br><br>"
|
||||
CHECK_TICK
|
||||
|
||||
|
||||
+20
-20
@@ -412,25 +412,25 @@
|
||||
|
||||
/proc/slot2body_zone(slot)
|
||||
switch(slot)
|
||||
if(SLOT_BACK, SLOT_WEAR_SUIT, SLOT_W_UNIFORM, SLOT_BELT, SLOT_WEAR_ID)
|
||||
if(ITEM_SLOT_BACK, ITEM_SLOT_OCLOTHING, ITEM_SLOT_ICLOTHING, ITEM_SLOT_BELT, ITEM_SLOT_ID)
|
||||
return BODY_ZONE_CHEST
|
||||
|
||||
if(SLOT_GLOVES, SLOT_HANDS, SLOT_HANDCUFFED)
|
||||
if(ITEM_SLOT_GLOVES, ITEM_SLOT_HANDS, ITEM_SLOT_HANDCUFFED)
|
||||
return pick(BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND)
|
||||
|
||||
if(SLOT_HEAD, SLOT_NECK, SLOT_NECK, SLOT_EARS)
|
||||
if(ITEM_SLOT_HEAD, ITEM_SLOT_NECK, ITEM_SLOT_NECK, ITEM_SLOT_EARS)
|
||||
return BODY_ZONE_HEAD
|
||||
|
||||
if(SLOT_WEAR_MASK)
|
||||
if(ITEM_SLOT_MASK)
|
||||
return BODY_ZONE_PRECISE_MOUTH
|
||||
|
||||
if(SLOT_GLASSES)
|
||||
if(ITEM_SLOT_EYES)
|
||||
return BODY_ZONE_PRECISE_EYES
|
||||
|
||||
if(SLOT_SHOES)
|
||||
if(ITEM_SLOT_FEET)
|
||||
return pick(BODY_ZONE_PRECISE_R_FOOT, BODY_ZONE_PRECISE_L_FOOT)
|
||||
|
||||
if(SLOT_LEGCUFFED)
|
||||
if(ITEM_SLOT_LEGCUFFED)
|
||||
return pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
|
||||
|
||||
//adapted from http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
|
||||
@@ -652,31 +652,31 @@
|
||||
|
||||
/proc/slot_to_string(slot)
|
||||
switch(slot)
|
||||
if(SLOT_BACK)
|
||||
if(ITEM_SLOT_BACK)
|
||||
return "Backpack"
|
||||
if(SLOT_WEAR_MASK)
|
||||
if(ITEM_SLOT_MASK)
|
||||
return "Mask"
|
||||
if(SLOT_HANDS)
|
||||
if(ITEM_SLOT_HANDS)
|
||||
return "Hands"
|
||||
if(SLOT_BELT)
|
||||
if(ITEM_SLOT_BELT)
|
||||
return "Belt"
|
||||
if(SLOT_EARS)
|
||||
if(ITEM_SLOT_EARS)
|
||||
return "Ears"
|
||||
if(SLOT_GLASSES)
|
||||
if(ITEM_SLOT_EYES)
|
||||
return "Glasses"
|
||||
if(SLOT_GLOVES)
|
||||
if(ITEM_SLOT_GLOVES)
|
||||
return "Gloves"
|
||||
if(SLOT_NECK)
|
||||
if(ITEM_SLOT_NECK)
|
||||
return "Neck"
|
||||
if(SLOT_HEAD)
|
||||
if(ITEM_SLOT_HEAD)
|
||||
return "Head"
|
||||
if(SLOT_SHOES)
|
||||
if(ITEM_SLOT_FEET)
|
||||
return "Shoes"
|
||||
if(SLOT_WEAR_SUIT)
|
||||
if(ITEM_SLOT_OCLOTHING)
|
||||
return "Suit"
|
||||
if(SLOT_W_UNIFORM)
|
||||
if(ITEM_SLOT_ICLOTHING)
|
||||
return "Uniform"
|
||||
if(SLOT_IN_BACKPACK)
|
||||
if(ITEM_SLOT_BACKPACK)
|
||||
return "In backpack"
|
||||
|
||||
/proc/tg_ui_icon_to_cit_ui(ui_style)
|
||||
|
||||
@@ -1600,7 +1600,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
|
||||
if(!iscarbon(target))
|
||||
return TRUE
|
||||
if(check_neck)
|
||||
if(istype(target.get_item_by_slot(SLOT_NECK), /obj/item/clothing/neck/garlic_necklace))
|
||||
if(istype(target.get_item_by_slot(ITEM_SLOT_NECK), /obj/item/clothing/neck/garlic_necklace))
|
||||
return FALSE
|
||||
if(check_blood)
|
||||
if(target.reagents.has_reagent(/datum/reagent/consumable/garlic))
|
||||
|
||||
@@ -160,6 +160,7 @@ GLOBAL_LIST_INIT(bitfields, list(
|
||||
"HOLOGRAM_1" = HOLOGRAM_1,
|
||||
"SHOCKED_1" = SHOCKED_1,
|
||||
"INITIALIZED_1" = INITIALIZED_1,
|
||||
"NO_SCREENTIPS_1" = NO_SCREENTIPS_1,
|
||||
"ADMIN_SPAWNED_1" = ADMIN_SPAWNED_1,
|
||||
"BLOCK_FACE_ATOM_1" = BLOCK_FACE_ATOM_1,
|
||||
"PREVENT_CONTENTS_EXPLOSION_1" = PREVENT_CONTENTS_EXPLOSION_1
|
||||
|
||||
@@ -16,6 +16,8 @@ GLOBAL_LIST_EMPTY(singularities) //list of all singularities on the stati
|
||||
GLOBAL_LIST_EMPTY(grounding_rods) //list of all grounding rods on the station
|
||||
|
||||
GLOBAL_LIST(chemical_reactions_list) //list of all /datum/chemical_reaction datums. Used during chemical reactions
|
||||
GLOBAL_LIST(drink_reactions_list) //list of all /datum/chemical_reaction datums where the output is of type /datum/reagent/consumable for bartender PDA
|
||||
GLOBAL_LIST(normalized_chemical_reactions_list) //list of all /datum/chemical_reaction datums with actual sane indexing for chemistry PDA
|
||||
GLOBAL_LIST(chemical_reagents_list) //list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff
|
||||
GLOBAL_LIST_EMPTY(tech_list) //list of all /datum/tech datums indexed by id.
|
||||
GLOBAL_LIST_EMPTY(surgeries_list) //list of all surgeries by name, associated with their path.
|
||||
|
||||
@@ -11,6 +11,8 @@ GLOBAL_VAR(world_qdel_log)
|
||||
GLOBAL_PROTECT(world_qdel_log)
|
||||
GLOBAL_VAR(world_attack_log)
|
||||
GLOBAL_PROTECT(world_attack_log)
|
||||
GLOBAL_VAR(world_victim_log)
|
||||
GLOBAL_PROTECT(world_victim_log)
|
||||
// GLOBAL_VAR(world_econ_log)
|
||||
// GLOBAL_PROTECT(world_econ_log)
|
||||
GLOBAL_VAR(world_href_log)
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
for(var/atom/movable/screen/inventory/inv in (static_inventory + toggleable_inventory))
|
||||
if(inv.slot_id)
|
||||
inv.hud = src
|
||||
inv_slots[inv.slot_id] = inv
|
||||
inv_slots[TOBITSHIFT(inv.slot_id) + 1] = inv
|
||||
inv.update_icon()
|
||||
|
||||
/datum/hud/alien/persistent_inventory_update()
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
inv_box.icon_state = "suit_storage"
|
||||
// inv_box.icon_full = "template"
|
||||
inv_box.screen_loc = ui_drone_storage
|
||||
inv_box.slot_id = SLOT_GENERC_DEXTROUS_STORAGE
|
||||
inv_box.slot_id = ITEM_SLOT_DEX_STORAGE
|
||||
static_inventory += inv_box
|
||||
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
@@ -17,13 +17,13 @@
|
||||
inv_box.icon_state = "mask"
|
||||
// inv_box.icon_full = "template"
|
||||
inv_box.screen_loc = ui_drone_head
|
||||
inv_box.slot_id = SLOT_HEAD
|
||||
inv_box.slot_id = ITEM_SLOT_HEAD
|
||||
static_inventory += inv_box
|
||||
|
||||
for(var/atom/movable/screen/inventory/inv in (static_inventory + toggleable_inventory))
|
||||
if(inv.slot_id)
|
||||
inv.hud = src
|
||||
inv_slots[inv.slot_id] = inv
|
||||
inv_slots[TOBITSHIFT(inv.slot_id) + 1] = inv
|
||||
inv.update_icon()
|
||||
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
for(var/atom/movable/screen/inventory/inv in (static_inventory + toggleable_inventory))
|
||||
if(inv.slot_id)
|
||||
inv.hud = src
|
||||
inv_slots[inv.slot_id] = inv
|
||||
inv_slots[TOBITSHIFT(inv.slot_id) + 1] = inv
|
||||
inv.update_icon()
|
||||
|
||||
/datum/hud/dextrous/persistent_inventory_update()
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "suit_storage"
|
||||
inv_box.screen_loc = ui_id
|
||||
inv_box.slot_id = SLOT_GENERC_DEXTROUS_STORAGE
|
||||
inv_box.slot_id = ITEM_SLOT_DEX_STORAGE
|
||||
static_inventory += inv_box
|
||||
|
||||
using = new /atom/movable/screen/guardian/Communicate()
|
||||
|
||||
@@ -53,6 +53,22 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
|
||||
var/list/hand_slots // /atom/movable/screen/inventory/hand objects, assoc list of "[held_index]" = object
|
||||
var/list/atom/movable/screen/plane_master/plane_masters = list() // see "appearance_flags" in the ref, assoc list of "[plane]" = object
|
||||
|
||||
|
||||
///UI for screentips that appear when you mouse over things
|
||||
var/atom/movable/screen/screentip/screentip_text
|
||||
|
||||
/// Whether or not screentips are enabled.
|
||||
/// This is updated by the preference for cheaper reads than would be
|
||||
/// had with a proc call, especially on one of the hottest procs in the
|
||||
/// game (MouseEntered).
|
||||
var/screentips_enabled = TRUE
|
||||
|
||||
/// The color to use for the screentips.
|
||||
/// This is updated by the preference for cheaper reads than would be
|
||||
/// had with a proc call, especially on one of the hottest procs in the
|
||||
/// game (MouseEntered).
|
||||
var/screentip_color
|
||||
|
||||
var/atom/movable/screen/movable/action_button/hide_toggle/hide_actions_toggle
|
||||
var/action_buttons_hidden = FALSE
|
||||
|
||||
@@ -83,6 +99,8 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
|
||||
plane_masters["[instance.plane]"] = instance
|
||||
instance.backdrop(mymob)
|
||||
|
||||
screentip_text = new(null, src)
|
||||
static_inventory += screentip_text
|
||||
|
||||
/datum/hud/Destroy()
|
||||
if(mymob.hud_used == src)
|
||||
@@ -117,6 +135,8 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
|
||||
QDEL_LIST(screenoverlays)
|
||||
mymob = null
|
||||
|
||||
QDEL_NULL(screentip_text)
|
||||
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
+16
-16
@@ -233,7 +233,7 @@
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
inv_box.name = "i_clothing"
|
||||
inv_box.icon = ui_style
|
||||
inv_box.slot_id = SLOT_W_UNIFORM
|
||||
inv_box.slot_id = ITEM_SLOT_ICLOTHING
|
||||
inv_box.icon_state = "uniform"
|
||||
inv_box.screen_loc = ui_iclothing
|
||||
toggleable_inventory += inv_box
|
||||
@@ -241,7 +241,7 @@
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
inv_box.name = "o_clothing"
|
||||
inv_box.icon = ui_style
|
||||
inv_box.slot_id = SLOT_WEAR_SUIT
|
||||
inv_box.slot_id = ITEM_SLOT_OCLOTHING
|
||||
inv_box.icon_state = "suit"
|
||||
inv_box.screen_loc = ui_oclothing
|
||||
toggleable_inventory += inv_box
|
||||
@@ -267,7 +267,7 @@
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "id"
|
||||
inv_box.screen_loc = ui_id
|
||||
inv_box.slot_id = SLOT_WEAR_ID
|
||||
inv_box.slot_id = ITEM_SLOT_ID
|
||||
static_inventory += inv_box
|
||||
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
@@ -275,7 +275,7 @@
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "mask"
|
||||
inv_box.screen_loc = ui_mask
|
||||
inv_box.slot_id = SLOT_WEAR_MASK
|
||||
inv_box.slot_id = ITEM_SLOT_MASK
|
||||
toggleable_inventory += inv_box
|
||||
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
@@ -283,7 +283,7 @@
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "neck"
|
||||
inv_box.screen_loc = ui_neck
|
||||
inv_box.slot_id = SLOT_NECK
|
||||
inv_box.slot_id = ITEM_SLOT_NECK
|
||||
toggleable_inventory += inv_box
|
||||
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
@@ -291,7 +291,7 @@
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "back"
|
||||
inv_box.screen_loc = ui_back
|
||||
inv_box.slot_id = SLOT_BACK
|
||||
inv_box.slot_id = ITEM_SLOT_BACK
|
||||
static_inventory += inv_box
|
||||
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
@@ -299,7 +299,7 @@
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "pocket"
|
||||
inv_box.screen_loc = ui_storage1
|
||||
inv_box.slot_id = SLOT_L_STORE
|
||||
inv_box.slot_id = ITEM_SLOT_LPOCKET
|
||||
static_inventory += inv_box
|
||||
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
@@ -307,7 +307,7 @@
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "pocket"
|
||||
inv_box.screen_loc = ui_storage2
|
||||
inv_box.slot_id = SLOT_R_STORE
|
||||
inv_box.slot_id = ITEM_SLOT_RPOCKET
|
||||
static_inventory += inv_box
|
||||
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
@@ -315,7 +315,7 @@
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "suit_storage"
|
||||
inv_box.screen_loc = ui_sstore1
|
||||
inv_box.slot_id = SLOT_S_STORE
|
||||
inv_box.slot_id = ITEM_SLOT_SUITSTORE
|
||||
static_inventory += inv_box
|
||||
|
||||
using = new /atom/movable/screen/resist()
|
||||
@@ -348,7 +348,7 @@
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "gloves"
|
||||
inv_box.screen_loc = ui_gloves
|
||||
inv_box.slot_id = SLOT_GLOVES
|
||||
inv_box.slot_id = ITEM_SLOT_GLOVES
|
||||
toggleable_inventory += inv_box
|
||||
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
@@ -356,7 +356,7 @@
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "glasses"
|
||||
inv_box.screen_loc = ui_glasses
|
||||
inv_box.slot_id = SLOT_GLASSES
|
||||
inv_box.slot_id = ITEM_SLOT_EYES
|
||||
toggleable_inventory += inv_box
|
||||
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
@@ -364,7 +364,7 @@
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "ears"
|
||||
inv_box.screen_loc = ui_ears
|
||||
inv_box.slot_id = SLOT_EARS
|
||||
inv_box.slot_id = ITEM_SLOT_EARS
|
||||
toggleable_inventory += inv_box
|
||||
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
@@ -372,7 +372,7 @@
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "head"
|
||||
inv_box.screen_loc = ui_head
|
||||
inv_box.slot_id = SLOT_HEAD
|
||||
inv_box.slot_id = ITEM_SLOT_HEAD
|
||||
toggleable_inventory += inv_box
|
||||
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
@@ -380,7 +380,7 @@
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "shoes"
|
||||
inv_box.screen_loc = ui_shoes
|
||||
inv_box.slot_id = SLOT_SHOES
|
||||
inv_box.slot_id = ITEM_SLOT_FEET
|
||||
toggleable_inventory += inv_box
|
||||
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
@@ -389,7 +389,7 @@
|
||||
inv_box.icon_state = "belt"
|
||||
// inv_box.icon_full = "template_small"
|
||||
inv_box.screen_loc = ui_belt
|
||||
inv_box.slot_id = SLOT_BELT
|
||||
inv_box.slot_id = ITEM_SLOT_BELT
|
||||
static_inventory += inv_box
|
||||
|
||||
throw_icon = new /atom/movable/screen/throw_catch()
|
||||
@@ -464,7 +464,7 @@
|
||||
for(var/atom/movable/screen/inventory/inv in (static_inventory + toggleable_inventory))
|
||||
if(inv.slot_id)
|
||||
inv.hud = src
|
||||
inv_slots[inv.slot_id] = inv
|
||||
inv_slots[TOBITSHIFT(inv.slot_id) + 1] = inv
|
||||
inv.update_icon()
|
||||
|
||||
update_locked_slots()
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
inv_box.icon_state = "mask"
|
||||
// inv_box.icon_full = "template"
|
||||
inv_box.screen_loc = ui_monkey_mask
|
||||
inv_box.slot_id = SLOT_WEAR_MASK
|
||||
inv_box.slot_id = ITEM_SLOT_MASK
|
||||
static_inventory += inv_box
|
||||
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
@@ -59,7 +59,7 @@
|
||||
inv_box.icon_state = "neck"
|
||||
// inv_box.icon_full = "template"
|
||||
inv_box.screen_loc = ui_monkey_neck
|
||||
inv_box.slot_id = SLOT_NECK
|
||||
inv_box.slot_id = ITEM_SLOT_NECK
|
||||
static_inventory += inv_box
|
||||
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
@@ -68,7 +68,7 @@
|
||||
inv_box.icon_state = "head"
|
||||
// inv_box.icon_full = "template"
|
||||
inv_box.screen_loc = ui_monkey_head
|
||||
inv_box.slot_id = SLOT_HEAD
|
||||
inv_box.slot_id = ITEM_SLOT_HEAD
|
||||
static_inventory += inv_box
|
||||
|
||||
inv_box = new /atom/movable/screen/inventory()
|
||||
@@ -76,7 +76,7 @@
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "back"
|
||||
inv_box.screen_loc = ui_monkey_back
|
||||
inv_box.slot_id = SLOT_BACK
|
||||
inv_box.slot_id = ITEM_SLOT_BACK
|
||||
static_inventory += inv_box
|
||||
|
||||
throw_icon = new /atom/movable/screen/throw_catch()
|
||||
@@ -126,7 +126,7 @@
|
||||
for(var/atom/movable/screen/inventory/inv in (static_inventory + toggleable_inventory))
|
||||
if(inv.slot_id)
|
||||
inv.hud = src
|
||||
inv_slots[inv.slot_id] = inv
|
||||
inv_slots[TOBITSHIFT(inv.slot_id) + 1] = inv
|
||||
inv.update_icon()
|
||||
|
||||
/datum/hud/monkey/persistent_inventory_update()
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/atom/movable/screen/screentip
|
||||
icon = null
|
||||
icon_state = null
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
screen_loc = "TOP,LEFT"
|
||||
maptext_height = 480
|
||||
maptext_width = 480
|
||||
maptext = ""
|
||||
|
||||
/atom/movable/screen/screentip/Initialize(mapload, _hud)
|
||||
. = ..()
|
||||
hud = _hud
|
||||
update_view()
|
||||
|
||||
/atom/movable/screen/screentip/proc/update_view(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
if(!hud || !hud.mymob.client.view_size) //Might not have been initialized by now
|
||||
return
|
||||
maptext_width = getviewsize(hud.mymob.client.view_size.getView())[1] * world.icon_size
|
||||
@@ -101,7 +101,7 @@
|
||||
|
||||
//stops TK grabs being equipped anywhere but into hands
|
||||
/obj/item/tk_grab/equipped(mob/user, slot)
|
||||
if(slot == SLOT_HANDS)
|
||||
if(slot == ITEM_SLOT_HANDS)
|
||||
return ..()
|
||||
qdel(src)
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@
|
||||
L.SetView(C.view, TRUE)
|
||||
. |= L
|
||||
C.screen |= .
|
||||
if(!secondary_map)
|
||||
if(!secondary_map && (owner.prefs.parallax != PARALLAX_DISABLE))
|
||||
var/atom/movable/screen/plane_master/parallax_white/PM = locate() in C.screen
|
||||
if(PM)
|
||||
PM.color = list(
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
P.pixel_x = planet_offset_x
|
||||
P.pixel_y = planet_offset_y
|
||||
. += P
|
||||
if(random_layer)
|
||||
if(ispath(random_layer, /atom/movable/screen/parallax_layer))
|
||||
. += new random_layer
|
||||
if(ispath(random_layer, /atom/movable/screen/parallax_layer/space/random/space_gas))
|
||||
var/atom/movable/screen/parallax_layer/space/random/space_gas/SG = locate(random_layer) in objects
|
||||
|
||||
@@ -94,6 +94,10 @@
|
||||
config_entry_value = 10
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/keyed_list/dynamic_mode_days
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_FLAG
|
||||
|
||||
/datum/config_entry/keyed_list/storyteller_weight
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_NUM
|
||||
|
||||
@@ -349,3 +349,9 @@
|
||||
/datum/config_entry/flag/dynamic_config_enabled
|
||||
|
||||
/datum/config_entry/flag/station_name_needs_approval
|
||||
|
||||
//ambition start
|
||||
/datum/config_entry/number/max_ambitions // Maximum number of ambitions a mind can store.
|
||||
config_entry_value = 5
|
||||
//ambition end
|
||||
|
||||
|
||||
@@ -1,88 +1,119 @@
|
||||
/datum/config_entry/flag/log_ooc // log OOC channel
|
||||
/// log OOC channel
|
||||
/datum/config_entry/flag/log_ooc
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_access // log login/logout
|
||||
/// log login/logout
|
||||
/datum/config_entry/flag/log_access
|
||||
config_entry_value = TRUE
|
||||
|
||||
/// Config entry which special logging of failed logins under suspicious circumstances.
|
||||
/datum/config_entry/flag/log_suspicious_login
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_say // log client say
|
||||
/// log client say
|
||||
/datum/config_entry/flag/log_say
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_admin // log admin actions
|
||||
/// log admin actions
|
||||
/datum/config_entry/flag/log_admin
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_prayer // log prayers
|
||||
/// log prayers
|
||||
/datum/config_entry/flag/log_prayer
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_law // log lawchanges
|
||||
/// log lawchanges
|
||||
/datum/config_entry/flag/log_law
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_game // log game events
|
||||
/// log game events
|
||||
/datum/config_entry/flag/log_game
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_virus // log virology data
|
||||
/// log virology data
|
||||
/datum/config_entry/flag/log_virus
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_vote // log voting
|
||||
/// log voting
|
||||
/datum/config_entry/flag/log_vote
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_craft // log crafting
|
||||
/// log crafting
|
||||
/datum/config_entry/flag/log_craft
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_whisper // log client whisper
|
||||
/// log client whisper
|
||||
/datum/config_entry/flag/log_whisper
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_attack // log attack messages
|
||||
/// log attack messages
|
||||
/datum/config_entry/flag/log_attack
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_emote // log emotes
|
||||
/// log attack messages
|
||||
/datum/config_entry/flag/log_victim
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_adminchat // log admin chat messages
|
||||
/// log emotes
|
||||
/datum/config_entry/flag/log_emote
|
||||
config_entry_value = TRUE
|
||||
|
||||
/// log admin chat messages
|
||||
/datum/config_entry/flag/log_adminchat
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/datum/config_entry/flag/log_shuttle // log shuttle related actions, ie shuttle computers, shuttle manipulator, emergency console
|
||||
/// log shuttle related actions, ie shuttle computers, shuttle manipulator, emergency console
|
||||
/datum/config_entry/flag/log_shuttle
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_pda // log pda messages
|
||||
/// log pda messages
|
||||
/datum/config_entry/flag/log_pda
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_telecomms // log telecomms messages
|
||||
/// log telecomms messages
|
||||
/datum/config_entry/flag/log_telecomms
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_twitter // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
|
||||
/// log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
|
||||
/datum/config_entry/flag/log_twitter
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_world_topic // log all world.Topic() calls
|
||||
/// log all world.Topic() calls
|
||||
/datum/config_entry/flag/log_world_topic
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_manifest // log crew manifest to seperate file
|
||||
/// log crew manifest to seperate file
|
||||
/datum/config_entry/flag/log_manifest
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_job_debug // log roundstart divide occupations debug information to a file
|
||||
/// log roundstart divide occupations debug information to a file
|
||||
/datum/config_entry/flag/log_job_debug
|
||||
config_entry_value = TRUE
|
||||
|
||||
/// log photos taken by players with a camera
|
||||
/datum/config_entry/flag/log_pictures
|
||||
|
||||
/// This is... shitcode, literally same as above, if one of them is inactive, won't log at all, PLEASE FUCKING REMOVE THIS.
|
||||
/datum/config_entry/flag/picture_logging_camera
|
||||
|
||||
/// forces log_href for tgui
|
||||
/datum/config_entry/flag/emergency_tgui_logging
|
||||
config_entry_value = FALSE
|
||||
|
||||
/datum/config_entry/number/error_cooldown // The "cooldown" time for each occurrence of a unique error
|
||||
/// The "cooldown" time for each occurrence of a unique error
|
||||
/datum/config_entry/number/error_cooldown
|
||||
config_entry_value = 600
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/error_limit // How many occurrences before the next will silence them
|
||||
/// How many occurrences before the next will silence them
|
||||
/datum/config_entry/number/error_limit
|
||||
config_entry_value = 50
|
||||
|
||||
/datum/config_entry/number/error_silence_time // How long a unique error will be silenced for
|
||||
/// How long a unique error will be silenced for
|
||||
/datum/config_entry/number/error_silence_time
|
||||
config_entry_value = 6000
|
||||
|
||||
/datum/config_entry/number/error_msg_delay // How long to wait between messaging admins about occurrences of a unique error
|
||||
/// How long to wait between messaging admins about occurrences of a unique error
|
||||
/datum/config_entry/number/error_msg_delay
|
||||
config_entry_value = 50
|
||||
|
||||
@@ -396,12 +396,15 @@ SUBSYSTEM_DEF(air)
|
||||
*/
|
||||
|
||||
/datum/controller/subsystem/air/proc/run_delay_heuristics()
|
||||
if(!equalize_enabled)
|
||||
cost_equalize = 0
|
||||
if(should_do_equalization)
|
||||
eq_cooldown--
|
||||
if(eq_cooldown <= 0)
|
||||
equalize_enabled = TRUE
|
||||
if(should_do_equalization)
|
||||
if(!equalize_enabled)
|
||||
cost_equalize = 0
|
||||
if(should_do_equalization)
|
||||
eq_cooldown--
|
||||
if(eq_cooldown <= 0)
|
||||
equalize_enabled = TRUE
|
||||
else
|
||||
equalize_enabled = FALSE
|
||||
var/total_thread_time = cost_turfs + cost_equalize + cost_groups + cost_post_process
|
||||
if(total_thread_time)
|
||||
var/wait_ms = wait * 100
|
||||
|
||||
@@ -500,7 +500,7 @@ SUBSYSTEM_DEF(job)
|
||||
tcg_cards = N.client.prefs.tcg_cards
|
||||
if(tcg_cards)
|
||||
var/obj/item/tcgcard_binder/binder = new(get_turf(H))
|
||||
H.equip_to_slot_if_possible(binder, SLOT_IN_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE)
|
||||
H.equip_to_slot_if_possible(binder, ITEM_SLOT_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE)
|
||||
for(var/card_type in N.client.prefs.tcg_cards)
|
||||
if(card_type)
|
||||
if(islist(H.client.prefs.tcg_cards[card_type]))
|
||||
@@ -710,9 +710,9 @@ SUBSYSTEM_DEF(job)
|
||||
permitted = FALSE
|
||||
if(G.donoritem && !G.donator_ckey_check(the_mob.client.ckey))
|
||||
permitted = FALSE
|
||||
if(!equipbackpackstuff && G.slot == SLOT_IN_BACKPACK)//snowflake check since plopping stuff in the backpack doesnt work for pre-job equip loadout stuffs
|
||||
if(!equipbackpackstuff && G.slot == ITEM_SLOT_BACKPACK)//snowflake check since plopping stuff in the backpack doesnt work for pre-job equip loadout stuffs
|
||||
permitted = FALSE
|
||||
if(equipbackpackstuff && G.slot != SLOT_IN_BACKPACK)//ditto
|
||||
if(equipbackpackstuff && G.slot != ITEM_SLOT_BACKPACK)//ditto
|
||||
permitted = FALSE
|
||||
if(!permitted)
|
||||
continue
|
||||
@@ -749,7 +749,7 @@ SUBSYSTEM_DEF(job)
|
||||
I.forceMove(get_turf(C))
|
||||
else
|
||||
qdel(I)
|
||||
else if(!M.equip_to_slot_if_possible(I, SLOT_IN_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) // Otherwise, try to put it in the backpack
|
||||
else if(!M.equip_to_slot_if_possible(I, ITEM_SLOT_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) // Otherwise, try to put it in the backpack
|
||||
if(can_drop)
|
||||
I.forceMove(get_turf(M)) // If everything fails, just put it on the floor under the mob.
|
||||
else
|
||||
|
||||
@@ -32,6 +32,8 @@ SUBSYSTEM_DEF(vote)
|
||||
|
||||
var/list/stored_modetier_results = list() // The aggregated tier list of the modes available in secret.
|
||||
|
||||
var/transfer_votes_done = 0
|
||||
|
||||
/datum/controller/subsystem/vote/fire() //called by master_controller
|
||||
if(mode)
|
||||
if(end_time < world.time)
|
||||
@@ -248,8 +250,18 @@ SUBSYSTEM_DEF(vote)
|
||||
if(vote_system == SCORE_VOTING)
|
||||
calculate_scores(vote_title_text)
|
||||
if(vote_system == HIGHEST_MEDIAN_VOTING)
|
||||
calculate_highest_median(vote_title_text) // nothing uses this at the moment
|
||||
var/list/winners = vote_system == INSTANT_RUNOFF_VOTING ? get_runoff_results() : get_result()
|
||||
calculate_highest_median(vote_title_text)
|
||||
var/list/winners = list()
|
||||
if(mode == "transfer")
|
||||
var/amount_required = 3 + transfer_votes_done
|
||||
transfer_votes_done += 1
|
||||
text += "\nExtending requires at least [amount_required] votes to win."
|
||||
if(choices[VOTE_CONTINUE] < amount_required || choices[VOTE_TRANSFER] >= choices[VOTE_CONTINUE])
|
||||
winners = list(VOTE_TRANSFER)
|
||||
else
|
||||
winners = list(VOTE_CONTINUE)
|
||||
else
|
||||
winners = vote_system == INSTANT_RUNOFF_VOTING ? get_runoff_results() : get_result()
|
||||
var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic"
|
||||
if(winners.len > 0)
|
||||
if(was_roundtype_vote)
|
||||
@@ -305,7 +317,7 @@ SUBSYSTEM_DEF(vote)
|
||||
if(vote_system == SCHULZE_VOTING)
|
||||
admintext += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!"
|
||||
else if(vote_system == HIGHEST_MEDIAN_VOTING)
|
||||
admintext += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!"
|
||||
admintext += "\nIt should be noted that this is not a raw tally of votes but rather the median score plus a tiebreaker!"
|
||||
for(var/i=1,i<=choices.len,i++)
|
||||
var/votes = choices[choices[i]]
|
||||
admintext += "\n<b>[choices[i]]:</b> [votes]"
|
||||
@@ -339,7 +351,7 @@ SUBSYSTEM_DEF(vote)
|
||||
if(SSmapping.changemap(config.maplist[.]))
|
||||
to_chat(world, "<span class='boldannounce'>The map vote has chosen [VM.map_name] for next round!</span>")
|
||||
if("transfer") // austation begin -- Crew autotransfer vote
|
||||
if(. == "Initiate Crew Transfer")
|
||||
if(. == VOTE_TRANSFER)
|
||||
SSshuttle.autoEnd()
|
||||
var/obj/machinery/computer/communications/C = locate() in GLOB.machines
|
||||
if(C)
|
||||
@@ -446,7 +458,7 @@ SUBSYSTEM_DEF(vote)
|
||||
continue
|
||||
choices |= M
|
||||
if("transfer") // austation begin -- Crew autotranfer vote
|
||||
choices.Add("Initiate Crew Transfer","Continue Playing") // austation end
|
||||
choices.Add(VOTE_TRANSFER,VOTE_CONTINUE) // austation end
|
||||
if("roundtype") //CIT CHANGE - adds the roundstart secret/extended vote
|
||||
choices.Add("dynamic", "extended")
|
||||
if("custom")
|
||||
|
||||
@@ -516,7 +516,7 @@
|
||||
H.attack_self(owner)
|
||||
return
|
||||
var/obj/item/I = target
|
||||
if(owner.can_equip(I, SLOT_HANDS))
|
||||
if(owner.can_equip(I, ITEM_SLOT_HANDS))
|
||||
owner.temporarilyRemoveItemFromInventory(I)
|
||||
owner.put_in_hands(I)
|
||||
I.attack_self(owner)
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
expire = _expire
|
||||
|
||||
/datum/component/anti_magic/proc/on_equip(datum/source, mob/equipper, slot)
|
||||
if(!(allowed_slots & slotdefine2slotbit(slot))) //Check that the slot is valid for antimagic
|
||||
if(!(allowed_slots & slot)) //Check that the slot is valid for antimagic
|
||||
UnregisterSignal(equipper, COMSIG_MOB_RECEIVE_MAGIC)
|
||||
return
|
||||
RegisterSignal(equipper, COMSIG_MOB_RECEIVE_MAGIC, .proc/protect, TRUE)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
var/filter_size
|
||||
var/filter_color
|
||||
|
||||
/datum/component/wearertargeting/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _color = "#E62111", list/_valid_slots = list(SLOT_GLASSES))
|
||||
/datum/component/wearertargeting/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _color = "#E62111", list/_valid_slots = list(ITEM_SLOT_EYES))
|
||||
. = ..()
|
||||
if(. == COMPONENT_INCOMPATIBLE)
|
||||
return
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
SSvis_overlays.add_vis_overlay(holder, 'icons/effects/effects.dmi', to_add, layer, GAME_PLANE, holder.dir)
|
||||
|
||||
/datum/component/shielded/proc/on_equip(obj/item/source, mob/living/equipper, slot)
|
||||
if(!(accepted_slots & slotdefine2slotbit(slot)))
|
||||
if(!(accepted_slots & slot))
|
||||
return
|
||||
holder = equipper
|
||||
RegisterSignal(parent, COMSIG_ITEM_RUN_BLOCK, .proc/on_run_block)
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
|
||||
/// Triggered on equip of the item containing the component
|
||||
/datum/component/two_handed/proc/on_equip(datum/source, mob/user, slot)
|
||||
if(require_twohands && slot == SLOT_HANDS) // force equip the item
|
||||
if(require_twohands && slot == ITEM_SLOT_HANDS) // force equip the item
|
||||
wield(user)
|
||||
if(!user.is_holding(parent) && wielded && !require_twohands)
|
||||
unwield(user)
|
||||
|
||||
@@ -235,6 +235,7 @@
|
||||
else
|
||||
return returned
|
||||
|
||||
|
||||
/**
|
||||
* Callback called by a timer to end an associative-list-indexed cooldown.
|
||||
*
|
||||
|
||||
@@ -75,8 +75,8 @@
|
||||
if(isobj(H.wear_suit))
|
||||
Cl = H.wear_suit
|
||||
passed = prob((Cl.permeability_coefficient*100) - 1)
|
||||
if(passed && isobj(SLOT_W_UNIFORM))
|
||||
Cl = SLOT_W_UNIFORM
|
||||
if(passed && isobj(ITEM_SLOT_ICLOTHING))
|
||||
Cl = ITEM_SLOT_ICLOTHING
|
||||
passed = prob((Cl.permeability_coefficient*100) - 1)
|
||||
if(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)
|
||||
if(isobj(H.wear_suit) && H.wear_suit.body_parts_covered&HANDS)
|
||||
|
||||
@@ -61,19 +61,19 @@ STI KALY - blind
|
||||
if(!istype(H.head, /obj/item/clothing/head/wizard))
|
||||
if(!H.dropItemToGround(H.head))
|
||||
qdel(H.head)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(H), SLOT_HEAD)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(H), ITEM_SLOT_HEAD)
|
||||
return
|
||||
if(prob(chance))
|
||||
if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe))
|
||||
if(!H.dropItemToGround(H.wear_suit))
|
||||
qdel(H.wear_suit)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(H), SLOT_WEAR_SUIT)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(H), ITEM_SLOT_OCLOTHING)
|
||||
return
|
||||
if(prob(chance))
|
||||
if(!istype(H.shoes, /obj/item/clothing/shoes/sandal/magic))
|
||||
if(!H.dropItemToGround(H.shoes))
|
||||
qdel(H.shoes)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal/magic(H), SLOT_SHOES)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal/magic(H), ITEM_SLOT_FEET)
|
||||
return
|
||||
else
|
||||
var/mob/living/carbon/H = affected_mob
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
user_by_item -= target
|
||||
|
||||
/datum/element/earhealing/proc/equippedChanged(datum/source, mob/living/carbon/user, slot)
|
||||
if(slot == SLOT_EARS && istype(user))
|
||||
if(slot == ITEM_SLOT_EARS && istype(user))
|
||||
user_by_item[source] = user
|
||||
else
|
||||
user_by_item -= source
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/element/polychromic/proc/grant_user_action(atom/source, mob/user, slot)
|
||||
if(slot == SLOT_IN_BACKPACK || slot == SLOT_LEGCUFFED || slot == SLOT_HANDCUFFED || slot == SLOT_GENERC_DEXTROUS_STORAGE)
|
||||
if(slot == ITEM_SLOT_BACKPACK || slot == ITEM_SLOT_LEGCUFFED || slot == ITEM_SLOT_HANDCUFFED || slot == ITEM_SLOT_DEX_STORAGE)
|
||||
return
|
||||
var/datum/action/polychromic/P = actions_by_atom[source]
|
||||
if(!P)
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
stacked_spellcasting_by_user -= target
|
||||
|
||||
/datum/element/spellcasting/proc/on_equip(datum/source, mob/equipper, slot)
|
||||
if(!(cast_slots & slotdefine2slotbit(slot)))
|
||||
if(!(cast_slots & slot))
|
||||
return
|
||||
users_by_item[source] = equipper
|
||||
if(!stacked_spellcasting_by_user[equipper])
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
/obj/item/clothing/gloves/boxing/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if(ishuman(user) && slot == SLOT_GLOVES)
|
||||
if(ishuman(user) && slot == ITEM_SLOT_GLOVES)
|
||||
var/mob/living/carbon/human/H = user
|
||||
style.teach(H,TRUE)
|
||||
|
||||
@@ -68,5 +68,5 @@
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.get_item_by_slot(SLOT_GLOVES) == src)
|
||||
if(H.get_item_by_slot(ITEM_SLOT_GLOVES) == src)
|
||||
style.remove(H)
|
||||
|
||||
@@ -197,7 +197,7 @@
|
||||
|
||||
/obj/item/clothing/gloves/krav_maga/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if(ishuman(user) && slot == SLOT_GLOVES)
|
||||
if(ishuman(user) && slot == ITEM_SLOT_GLOVES)
|
||||
var/mob/living/carbon/human/H = user
|
||||
style.teach(H,1)
|
||||
|
||||
@@ -206,7 +206,7 @@
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.get_item_by_slot(SLOT_GLOVES) == src)
|
||||
if(H.get_item_by_slot(ITEM_SLOT_GLOVES) == src)
|
||||
style.remove(H)
|
||||
|
||||
/obj/item/clothing/gloves/krav_maga/sec//more obviously named, given to sec
|
||||
|
||||
@@ -485,7 +485,7 @@
|
||||
|
||||
/obj/item/storage/belt/champion/wrestling/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if(ishuman(user) && slot == SLOT_BELT)
|
||||
if(ishuman(user) && slot == ITEM_SLOT_BELT)
|
||||
var/mob/living/carbon/human/H = user
|
||||
style.teach(H,1)
|
||||
|
||||
@@ -494,7 +494,7 @@
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.get_item_by_slot(SLOT_BELT) == src)
|
||||
if(H.get_item_by_slot(ITEM_SLOT_BELT) == src)
|
||||
style.remove(H)
|
||||
|
||||
//Subtype of wrestling, reserved for the wrestling belts found in the holodeck
|
||||
|
||||
+955
-39
File diff suppressed because it is too large
Load Diff
@@ -17,18 +17,18 @@
|
||||
if(!istype(H.wear_mask, /obj/item/clothing/mask/gas/cluwne))
|
||||
if(!H.dropItemToGround(H.wear_mask))
|
||||
qdel(H.wear_mask)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/cluwne(H), SLOT_WEAR_MASK)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/cluwne(H), ITEM_SLOT_MASK)
|
||||
if(!istype(H.w_uniform, /obj/item/clothing/under/cluwne))
|
||||
if(!H.dropItemToGround(H.w_uniform))
|
||||
qdel(H.w_uniform)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/under/cluwne(H), SLOT_W_UNIFORM)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/under/cluwne(H), ITEM_SLOT_ICLOTHING)
|
||||
if(!istype(H.shoes, /obj/item/clothing/shoes/clown_shoes/cluwne))
|
||||
if(!H.dropItemToGround(H.shoes))
|
||||
qdel(H.shoes)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes/cluwne(H), SLOT_SHOES)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes/cluwne(H), ITEM_SLOT_FEET)
|
||||
|
||||
owner.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/white(owner), SLOT_GLOVES) // this is purely for cosmetic purposes incase they aren't wearing anything in that slot
|
||||
owner.equip_to_slot_or_del(new /obj/item/storage/backpack/clown(owner), SLOT_BACK) // ditto
|
||||
owner.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/white(owner), ITEM_SLOT_GLOVES) // this is purely for cosmetic purposes incase they aren't wearing anything in that slot
|
||||
owner.equip_to_slot_or_del(new /obj/item/storage/backpack/clown(owner), ITEM_SLOT_BACK) // ditto
|
||||
|
||||
/datum/mutation/human/cluwne/on_life(mob/living/carbon/human/owner)
|
||||
if((prob(15) && owner.IsUnconscious()))
|
||||
|
||||
+16
-16
@@ -153,31 +153,31 @@
|
||||
|
||||
//Start with uniform,suit,backpack for additional slots
|
||||
if(uniform)
|
||||
H.equip_to_slot_or_del(new uniform(H), SLOT_W_UNIFORM, TRUE)
|
||||
H.equip_to_slot_or_del(new uniform(H), ITEM_SLOT_ICLOTHING, TRUE)
|
||||
if(suit)
|
||||
H.equip_to_slot_or_del(new suit(H), SLOT_WEAR_SUIT, TRUE)
|
||||
H.equip_to_slot_or_del(new suit(H), ITEM_SLOT_OCLOTHING, TRUE)
|
||||
if(back)
|
||||
H.equip_to_slot_or_del(new back(H), SLOT_BACK, TRUE)
|
||||
H.equip_to_slot_or_del(new back(H), ITEM_SLOT_BACK, TRUE)
|
||||
if(belt)
|
||||
H.equip_to_slot_or_del(new belt(H), SLOT_BELT, TRUE)
|
||||
H.equip_to_slot_or_del(new belt(H), ITEM_SLOT_BELT, TRUE)
|
||||
if(gloves)
|
||||
H.equip_to_slot_or_del(new gloves(H), SLOT_GLOVES, TRUE)
|
||||
H.equip_to_slot_or_del(new gloves(H), ITEM_SLOT_GLOVES, TRUE)
|
||||
if(shoes)
|
||||
H.equip_to_slot_or_del(new shoes(H), SLOT_SHOES, TRUE)
|
||||
H.equip_to_slot_or_del(new shoes(H), ITEM_SLOT_FEET, TRUE)
|
||||
if(head)
|
||||
H.equip_to_slot_or_del(new head(H), SLOT_HEAD, TRUE)
|
||||
H.equip_to_slot_or_del(new head(H), ITEM_SLOT_HEAD, TRUE)
|
||||
if(mask)
|
||||
H.equip_to_slot_or_del(new mask(H), SLOT_WEAR_MASK, TRUE)
|
||||
H.equip_to_slot_or_del(new mask(H), ITEM_SLOT_MASK, TRUE)
|
||||
if(neck)
|
||||
H.equip_to_slot_or_del(new neck(H), SLOT_NECK, TRUE)
|
||||
H.equip_to_slot_or_del(new neck(H), ITEM_SLOT_NECK, TRUE)
|
||||
if(ears)
|
||||
H.equip_to_slot_or_del(new ears(H), SLOT_EARS, TRUE)
|
||||
H.equip_to_slot_or_del(new ears(H), ITEM_SLOT_EARS, TRUE)
|
||||
if(glasses)
|
||||
H.equip_to_slot_or_del(new glasses(H), SLOT_GLASSES, TRUE)
|
||||
H.equip_to_slot_or_del(new glasses(H), ITEM_SLOT_EYES, TRUE)
|
||||
if(id)
|
||||
H.equip_to_slot_or_del(new id(H), SLOT_WEAR_ID, TRUE)
|
||||
H.equip_to_slot_or_del(new id(H), ITEM_SLOT_ID, TRUE)
|
||||
if(suit_store)
|
||||
H.equip_to_slot_or_del(new suit_store(H), SLOT_S_STORE, TRUE)
|
||||
H.equip_to_slot_or_del(new suit_store(H), ITEM_SLOT_SUITSTORE, TRUE)
|
||||
if(undershirt)
|
||||
H.undershirt = initial(undershirt.name)
|
||||
|
||||
@@ -195,9 +195,9 @@
|
||||
|
||||
if(!visualsOnly) // Items in pockets or backpack don't show up on mob's icon.
|
||||
if(l_pocket)
|
||||
H.equip_to_slot_or_del(new l_pocket(H), SLOT_L_STORE, TRUE)
|
||||
H.equip_to_slot_or_del(new l_pocket(H), ITEM_SLOT_LPOCKET, TRUE)
|
||||
if(r_pocket)
|
||||
H.equip_to_slot_or_del(new r_pocket(H), SLOT_R_STORE, TRUE)
|
||||
H.equip_to_slot_or_del(new r_pocket(H), ITEM_SLOT_RPOCKET, TRUE)
|
||||
|
||||
if(box)
|
||||
if(!backpack_contents)
|
||||
@@ -211,7 +211,7 @@
|
||||
if(!isnum(number))//Default to 1
|
||||
number = 1
|
||||
for(var/i in 1 to number)
|
||||
H.equip_to_slot_or_del(new path(H), SLOT_IN_BACKPACK, TRUE)
|
||||
H.equip_to_slot_or_del(new path(H), ITEM_SLOT_BACKPACK, TRUE)
|
||||
|
||||
if(!H.head && toggle_helmet && istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit))
|
||||
var/obj/item/clothing/suit/space/hardsuit/HS = H.wear_suit
|
||||
|
||||
@@ -578,8 +578,12 @@
|
||||
/datum/status_effect/regenerative_core/on_apply()
|
||||
. = ..()
|
||||
ADD_TRAIT(owner, TRAIT_IGNOREDAMAGESLOWDOWN, "regenerative_core")
|
||||
|
||||
if(HAS_TRAIT(owner, TRAIT_ROBOTIC_ORGANISM)) //Robots can heal from cores, but only get 1/5th of the healing. They can use this to get past the damage threshhold however, and then regularely heal from there.
|
||||
var/turf/T = get_turf(owner)
|
||||
if(T && is_mining_level(T.z))
|
||||
if(HAS_TRAIT(owner, TRAIT_ROBOTIC_ORGANISM)) //Robots can heal from cores, though they ""only"" heal 20 brute + burn damage each instead of 25
|
||||
heal_amount *= 0.8
|
||||
else
|
||||
duration = 10 SECONDS
|
||||
heal_amount *= 0.2
|
||||
owner.adjustBruteLoss(-heal_amount, only_organic = FALSE)
|
||||
if(!AmBloodsucker(owner)) //use your coffin you lazy bastard
|
||||
|
||||
@@ -1005,11 +1005,15 @@
|
||||
/datum/status_effect/trance/proc/hypnotize(datum/source, list/hearing_args)
|
||||
if(!owner.can_hear())
|
||||
return
|
||||
if(hearing_args[HEARING_SPEAKER] == owner)
|
||||
var/mob/hearing_speaker = hearing_args[HEARING_SPEAKER]
|
||||
if(hearing_speaker == owner)
|
||||
return
|
||||
var/mob/living/carbon/C = owner
|
||||
var/hypnomsg = uncostumize_say(hearing_args[HEARING_RAW_MESSAGE], hearing_args[HEARING_MESSAGE_MODE])
|
||||
C.cure_trauma_type(/datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY) //clear previous hypnosis
|
||||
// The brain trauma itself does its own set of logging, but this is the only place the source of the hypnosis phrase can be found.
|
||||
hearing_speaker.log_message("has hypnotised [key_name(C)] with the phrase '[hypnomsg]'", LOG_ATTACK)
|
||||
C.log_message("has been hypnotised by the phrase '[hypnomsg]' spoken by [key_name(hearing_speaker)]", LOG_VICTIM, log_globally = FALSE)
|
||||
addtimer(CALLBACK(C, /mob/living/carbon.proc/gain_trauma, /datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY, hypnomsg), 10)
|
||||
addtimer(CALLBACK(C, /mob/living.proc/Stun, 60, TRUE, TRUE), 15) //Take some time to think about it
|
||||
qdel(src)
|
||||
|
||||
@@ -129,7 +129,7 @@ Use this as a guideline
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
var/obj/item/clothing/glasses/regular/glasses = new(get_turf(H))
|
||||
H.put_in_hands(glasses)
|
||||
H.equip_to_slot(glasses, SLOT_GLASSES)
|
||||
H.equip_to_slot(glasses, ITEM_SLOT_EYES)
|
||||
H.regenerate_icons()
|
||||
|
||||
//This whole proc is called automatically
|
||||
|
||||
@@ -108,10 +108,10 @@
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
var/obj/item/choice_beacon/music/B = new(get_turf(H))
|
||||
H.put_in_hands(B)
|
||||
H.equip_to_slot_if_possible(B, SLOT_IN_BACKPACK)
|
||||
H.equip_to_slot_if_possible(B, ITEM_SLOT_BACKPACK)
|
||||
var/obj/item/musicaltuner/musicaltuner = new(get_turf(H))
|
||||
H.put_in_hands(musicaltuner)
|
||||
H.equip_to_slot_if_possible(musicaltuner, SLOT_IN_BACKPACK)
|
||||
H.equip_to_slot_if_possible(musicaltuner, ITEM_SLOT_BACKPACK)
|
||||
H.regenerate_icons()
|
||||
|
||||
/datum/quirk/photographer
|
||||
@@ -127,7 +127,7 @@
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
var/obj/item/camera/camera = new(get_turf(H))
|
||||
H.put_in_hands(camera)
|
||||
H.equip_to_slot(camera, SLOT_NECK)
|
||||
H.equip_to_slot(camera, ITEM_SLOT_NECK)
|
||||
H.regenerate_icons()
|
||||
|
||||
/datum/quirk/selfaware
|
||||
@@ -166,7 +166,7 @@
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
var/obj/item/toy/crayon/spraycan/spraycan = new(get_turf(H))
|
||||
H.put_in_hands(spraycan)
|
||||
H.equip_to_slot(spraycan, SLOT_IN_BACKPACK)
|
||||
H.equip_to_slot(spraycan, ITEM_SLOT_BACKPACK)
|
||||
H.regenerate_icons()
|
||||
|
||||
/datum/quirk/voracious
|
||||
@@ -188,7 +188,7 @@
|
||||
/datum/quirk/trandening/on_spawn()
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
var/obj/item/autosurgeon/gloweyes/gloweyes = new(get_turf(H))
|
||||
H.equip_to_slot(gloweyes, SLOT_IN_BACKPACK)
|
||||
H.equip_to_slot(gloweyes, ITEM_SLOT_BACKPACK)
|
||||
H.regenerate_icons()
|
||||
|
||||
/datum/quirk/bloodpressure
|
||||
|
||||
@@ -57,9 +57,9 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
|
||||
heirloom = new heirloom_type(get_turf(quirk_holder))
|
||||
GLOB.family_heirlooms += heirloom
|
||||
var/list/slots = list(
|
||||
"in your left pocket" = SLOT_L_STORE,
|
||||
"in your right pocket" = SLOT_R_STORE,
|
||||
"in your backpack" = SLOT_IN_BACKPACK
|
||||
"in your left pocket" = ITEM_SLOT_LPOCKET,
|
||||
"in your right pocket" = ITEM_SLOT_RPOCKET,
|
||||
"in your backpack" = ITEM_SLOT_BACKPACK
|
||||
)
|
||||
where = H.equip_in_one_of_slots(heirloom, slots, FALSE) || "at your feet"
|
||||
|
||||
@@ -120,7 +120,7 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
|
||||
/datum/quirk/nearsighted/on_spawn()
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
var/obj/item/clothing/glasses/regular/glasses = new(get_turf(H))
|
||||
if(!H.equip_to_slot_if_possible(glasses, SLOT_GLASSES))
|
||||
if(!H.equip_to_slot_if_possible(glasses, ITEM_SLOT_EYES))
|
||||
H.put_in_hands(glasses)
|
||||
|
||||
/datum/quirk/nyctophobia
|
||||
@@ -383,7 +383,7 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
|
||||
/datum/quirk/blindness/on_spawn()
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
var/obj/item/clothing/glasses/sunglasses/blindfold/white/glasses = new(get_turf(H))
|
||||
if(!H.equip_to_slot_if_possible(glasses, SLOT_GLASSES, bypass_equip_delay_self = TRUE)) //if you can't put it on the user's eyes, put it in their hands, otherwise put it on their eyes eyes
|
||||
if(!H.equip_to_slot_if_possible(glasses, ITEM_SLOT_EYES, bypass_equip_delay_self = TRUE)) //if you can't put it on the user's eyes, put it in their hands, otherwise put it on their eyes eyes
|
||||
H.put_in_hands(glasses)
|
||||
H.regenerate_icons()
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
/datum/quirk/colorist/on_spawn()
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
var/obj/item/dyespray/spraycan = new(get_turf(quirk_holder))
|
||||
H.equip_to_slot(spraycan, SLOT_IN_BACKPACK)
|
||||
H.equip_to_slot(spraycan, ITEM_SLOT_BACKPACK)
|
||||
H.regenerate_icons()
|
||||
|
||||
/datum/quirk/colorist/post_add()
|
||||
|
||||
+9
-8
@@ -1215,7 +1215,7 @@
|
||||
|
||||
if(user != target)
|
||||
var/reverse_message = "has been [what_done] by [ssource][postfix]"
|
||||
target.log_message(reverse_message, LOG_ATTACK, color="orange", log_globally=FALSE)
|
||||
target.log_message(reverse_message, LOG_VICTIM, color="orange", log_globally=FALSE)
|
||||
|
||||
/**
|
||||
* log_wound() is for when someone is *attacked* and suffers a wound. Note that this only captures wounds from damage, so smites/forced wounds aren't logged, as well as demotions like cuts scabbing over
|
||||
@@ -1406,11 +1406,12 @@
|
||||
//Update the screentip to reflect what we're hoverin over
|
||||
/atom/MouseEntered(location, control, params)
|
||||
. = ..()
|
||||
// Statusbar
|
||||
// status_bar_set_text(usr, name)
|
||||
// Screentips
|
||||
// if(usr?.hud_used)
|
||||
// if(!usr.client?.prefs.screentip_pref || (flags_1 & NO_SCREENTIPS_1))
|
||||
// usr.hud_used.screentip_text.maptext = ""
|
||||
// else
|
||||
// usr.hud_used.screentip_text.maptext = MAPTEXT("<span style='text-align: center'><span style='font-size: 32px'><span style='color:[usr.client.prefs.screentip_color]: 32px'>[name]</span>")
|
||||
var/client/client = usr?.client
|
||||
var/datum/hud/active_hud = client?.mob?.hud_used
|
||||
if(active_hud)
|
||||
if(!client.prefs.screentip_pref || (flags_1 & NO_SCREENTIPS_1))
|
||||
active_hud.screentip_text.maptext = ""
|
||||
else
|
||||
//We inline a MAPTEXT() here, because there's no good way to statically add to a string like this
|
||||
active_hud.screentip_text.maptext = MAPTEXT("<span style='text-align: center; font-size: 32px; color: [client?.prefs?.screentip_color]'>[name]</span>")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
GLOBAL_LIST_INIT(possible_changeling_IDs, list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega"))
|
||||
GLOBAL_LIST_INIT(slots, list("head", "wear_mask", "back", "wear_suit", "w_uniform", "shoes", "belt", "gloves", "glasses", "ears", "wear_id", "s_store"))
|
||||
GLOBAL_LIST_INIT(slot2slot, list("head" = SLOT_HEAD, "wear_mask" = SLOT_WEAR_MASK, "neck" = SLOT_NECK, "back" = SLOT_BACK, "wear_suit" = SLOT_WEAR_SUIT, "w_uniform" = SLOT_W_UNIFORM, "shoes" = SLOT_SHOES, "belt" = SLOT_BELT, "gloves" = SLOT_GLOVES, "glasses" = SLOT_GLASSES, "ears" = SLOT_EARS, "wear_id" = SLOT_WEAR_ID, "s_store" = SLOT_S_STORE))
|
||||
GLOBAL_LIST_INIT(slot2slot, list("head" = ITEM_SLOT_HEAD, "wear_mask" = ITEM_SLOT_MASK, "neck" = ITEM_SLOT_NECK, "back" = ITEM_SLOT_BACK, "wear_suit" = ITEM_SLOT_OCLOTHING, "w_uniform" = ITEM_SLOT_ICLOTHING, "shoes" = ITEM_SLOT_FEET, "belt" = ITEM_SLOT_BELT, "gloves" = ITEM_SLOT_GLOVES, "glasses" = ITEM_SLOT_EYES, "ears" = ITEM_SLOT_EARS, "wear_id" = ITEM_SLOT_ID, "s_store" = ITEM_SLOT_SUITSTORE))
|
||||
GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "wear_mask" = /obj/item/clothing/mask/changeling, "back" = /obj/item/changeling, "wear_suit" = /obj/item/clothing/suit/changeling, "w_uniform" = /obj/item/clothing/under/changeling, "shoes" = /obj/item/clothing/shoes/changeling, "belt" = /obj/item/changeling, "gloves" = /obj/item/clothing/gloves/changeling, "glasses" = /obj/item/clothing/glasses/changeling, "ears" = /obj/item/changeling, "wear_id" = /obj/item/changeling, "s_store" = /obj/item/changeling))
|
||||
GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our this objective to all lings
|
||||
|
||||
|
||||
@@ -205,11 +205,11 @@ Credit where due:
|
||||
var/mob/living/carbon/human/L = M
|
||||
var/obj/item/clockwork/slab/S = new
|
||||
var/slot = "At your feet"
|
||||
var/list/slots = list("In your left pocket" = SLOT_L_STORE, "In your right pocket" = SLOT_R_STORE, "In your backpack" = SLOT_IN_BACKPACK)
|
||||
var/list/slots = list("In your left pocket" = ITEM_SLOT_LPOCKET, "In your right pocket" = ITEM_SLOT_RPOCKET, "In your backpack" = ITEM_SLOT_BACKPACK)
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
var/obj/item/clockwork/replica_fabricator/F = new
|
||||
if(H.equip_to_slot_or_del(F, SLOT_IN_BACKPACK))
|
||||
if(H.equip_to_slot_or_del(F, ITEM_SLOT_BACKPACK))
|
||||
to_chat(H, "<span class='brass'>You have been equipped with a replica fabricator, an advanced tool that can convert objects like doors, tables or even coats into clockwork equivalents.</span>")
|
||||
slot = H.equip_in_one_of_slots(S, slots)
|
||||
if(slot == "In your backpack")
|
||||
|
||||
@@ -37,17 +37,17 @@
|
||||
if(!H.w_uniform || H.dropItemToGround(H.w_uniform))
|
||||
C = new /obj/item/clothing/under/rank/civilian/clown(H)
|
||||
ADD_TRAIT(C, TRAIT_NODROP, CLOWN_NUKE_TRAIT)
|
||||
H.equip_to_slot_or_del(C, SLOT_W_UNIFORM)
|
||||
H.equip_to_slot_or_del(C, ITEM_SLOT_ICLOTHING)
|
||||
|
||||
if(!H.shoes || H.dropItemToGround(H.shoes))
|
||||
C = new /obj/item/clothing/shoes/clown_shoes(H)
|
||||
ADD_TRAIT(C, TRAIT_NODROP, CLOWN_NUKE_TRAIT)
|
||||
H.equip_to_slot_or_del(C, SLOT_SHOES)
|
||||
H.equip_to_slot_or_del(C, ITEM_SLOT_FEET)
|
||||
|
||||
if(!H.wear_mask || H.dropItemToGround(H.wear_mask))
|
||||
C = new /obj/item/clothing/mask/gas/clown_hat(H)
|
||||
ADD_TRAIT(C, TRAIT_NODROP, CLOWN_NUKE_TRAIT)
|
||||
H.equip_to_slot_or_del(C, SLOT_WEAR_MASK)
|
||||
H.equip_to_slot_or_del(C, ITEM_SLOT_MASK)
|
||||
|
||||
H.dna.add_mutation(CLOWNMUT)
|
||||
H.dna.add_mutation(SMILE)
|
||||
|
||||
@@ -214,7 +214,7 @@
|
||||
if(!istype(C.wear_mask, /obj/item/clothing/mask/gas/clown_hat) && !istype(C.wear_mask, /obj/item/clothing/mask/gas/mime))
|
||||
if(!C.wear_mask || C.dropItemToGround(C.wear_mask))
|
||||
var/obj/item/clothing/mask/fakemoustache/sticky/the_stash = new /obj/item/clothing/mask/fakemoustache/sticky()
|
||||
C.equip_to_slot_or_del(the_stash, SLOT_WEAR_MASK, TRUE, TRUE, TRUE, TRUE)
|
||||
C.equip_to_slot_or_del(the_stash, ITEM_SLOT_MASK, TRUE, TRUE, TRUE, TRUE)
|
||||
|
||||
/obj/item/clothing/mask/fakemoustache/sticky
|
||||
var/unstick_time = 2 MINUTES
|
||||
@@ -226,7 +226,7 @@
|
||||
|
||||
/obj/item/clothing/mask/fakemoustache/sticky/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if(slot == SLOT_WEAR_MASK)
|
||||
if(slot == ITEM_SLOT_MASK)
|
||||
ADD_TRAIT(user, TRAIT_NO_INTERNALS, STICKY_MOUSTACHE_TRAIT)
|
||||
|
||||
/obj/item/clothing/mask/fakemoustache/sticky/dropped(mob/user)
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
|
||||
if(tc)
|
||||
var/obj/item/U = new uplink_type(H, H.key, tc)
|
||||
H.equip_to_slot_or_del(U, SLOT_IN_BACKPACK)
|
||||
H.equip_to_slot_or_del(U, ITEM_SLOT_BACKPACK)
|
||||
|
||||
var/obj/item/implant/weapons_auth/W = new
|
||||
W.implant(H)
|
||||
@@ -170,7 +170,7 @@
|
||||
mask = /obj/item/clothing/mask/gas/syndicate
|
||||
suit = /obj/item/clothing/suit/space/hardsuit/syndi
|
||||
r_pocket = /obj/item/tank/internals/emergency_oxygen/engi
|
||||
internals_slot = SLOT_R_STORE
|
||||
internals_slot = ITEM_SLOT_RPOCKET
|
||||
belt = /obj/item/storage/belt/military
|
||||
r_hand = /obj/item/gun/ballistic/automatic/shotgun/bulldog
|
||||
backpack_contents = list(/obj/item/storage/box/survival/syndie=1,\
|
||||
@@ -186,7 +186,7 @@
|
||||
suit = /obj/item/clothing/suit/space/syndicate/black/red
|
||||
head = /obj/item/clothing/head/helmet/space/syndicate/black/red
|
||||
r_pocket = /obj/item/tank/internals/emergency_oxygen/engi
|
||||
internals_slot = SLOT_R_STORE
|
||||
internals_slot = ITEM_SLOT_RPOCKET
|
||||
belt = /obj/item/storage/belt/military
|
||||
backpack_contents = list(/obj/item/storage/box/survival/syndie=1,\
|
||||
/obj/item/tank/jetpack/oxygen/harness=1,\
|
||||
|
||||
@@ -165,7 +165,7 @@ If not set, defaults to check_completion instead. Set it. It's used by cryo.
|
||||
if(receiver && receiver.current)
|
||||
if(ishuman(receiver.current))
|
||||
var/mob/living/carbon/human/H = receiver.current
|
||||
var/list/slots = list("backpack" = SLOT_IN_BACKPACK)
|
||||
var/list/slots = list("backpack" = ITEM_SLOT_BACKPACK)
|
||||
for(var/eq_path in special_equipment)
|
||||
var/obj/O = new eq_path
|
||||
. += O
|
||||
@@ -1197,7 +1197,7 @@ GLOBAL_LIST_EMPTY(cult_contraband)
|
||||
I.forceMove(get_turf(owner))
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.equip_in_one_of_slots(I, list("backpack" = SLOT_IN_BACKPACK), critical = TRUE)
|
||||
H.equip_in_one_of_slots(I, list("backpack" = ITEM_SLOT_BACKPACK), critical = TRUE)
|
||||
hoarded_item = I
|
||||
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
rad_insulation = RAD_MEDIUM_INSULATION
|
||||
|
||||
var/static/list/airlock_overlays = list()
|
||||
|
||||
|
||||
/// sigh
|
||||
var/unelectrify_timerid
|
||||
|
||||
@@ -1278,8 +1278,8 @@
|
||||
assemblytype = /obj/structure/door_assembly/door_assembly_extmai
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/door/airlock/CanAStarPass(obj/item/card/id/ID)
|
||||
//Airlock is passable if it is open (!density), bot has access, and is not bolted shut or powered off)
|
||||
/obj/machinery/door/airlock/CanAStarPass(obj/item/card/id/ID, to_dir, atom/movable/caller)
|
||||
//Airlock is passable if it is open (!density), bot has access, and is not bolted shut or powered off)
|
||||
return !density || (check_access(ID) && !locked && hasPower())
|
||||
|
||||
/obj/machinery/door/airlock/emag_act(mob/user)
|
||||
|
||||
@@ -52,23 +52,30 @@
|
||||
|
||||
/obj/machinery/limbgrower/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
for(var/datum/reagent/reagent_id in reagents.reagent_list)
|
||||
var/list/reagent_data = list(
|
||||
reagent_name = reagent_id.name,
|
||||
reagent_amount = reagent_id.volume,
|
||||
reagent_type = reagent_id.type
|
||||
)
|
||||
data["reagents"] += list(reagent_data)
|
||||
|
||||
if(reagents.reagent_list.len)
|
||||
for(var/datum/reagent/reagent_id in reagents.reagent_list)
|
||||
var/list/reagent_data = list(
|
||||
reagent_name = reagent_id.name,
|
||||
reagent_amount = reagent_id.volume,
|
||||
reagent_type = reagent_id.type
|
||||
)
|
||||
data["reagents"] += list(reagent_data)
|
||||
else
|
||||
data["reagents"] = list()
|
||||
data["total_reagents"] = reagents.total_volume
|
||||
data["max_reagents"] = reagents.maximum_volume
|
||||
data["busy"] = busy
|
||||
var/list/disk_data = list()
|
||||
disk_data["disk"] = dna_disk //Do i, the machine, have a disk?
|
||||
disk_data["name"] = dna_disk?.fields["name"] //Name for the human saved if there is one
|
||||
if(dna_disk)
|
||||
if(dna_disk.fields["name"])
|
||||
disk_data["name"] = dna_disk.fields["name"]
|
||||
else if(dna_disk.genetic_makeup_buffer["name"])
|
||||
disk_data["name"] = dna_disk.genetic_makeup_buffer["name"]
|
||||
else
|
||||
disk_data["name"] = "No name"
|
||||
//Name for the human saved if there is one
|
||||
data["disk"] = disk_data
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/limbgrower/ui_static_data(mob/user)
|
||||
@@ -119,6 +126,18 @@
|
||||
if (busy)
|
||||
to_chat(user, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
|
||||
return
|
||||
if(ispath(user_item.type, /obj/item/reagent_containers/blood) && user.a_intent != INTENT_HARM)
|
||||
var/obj/item/reagent_containers/blood/B = user_item
|
||||
if(!B.reagents.get_reagents())
|
||||
to_chat(user, "<span class=\"alert\">You can't fill [src] with an empty [B.name]!</span>")
|
||||
return
|
||||
if(reagents.total_volume == reagents.maximum_volume)
|
||||
to_chat(user, "<span class=\"alert\">\The [src] can't hold more blood!</span>")
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] drains the [user_item] into [src] using the blood bag port on [src].</span>",
|
||||
"You drain the [user_item] into [src] using the blood bag port.")
|
||||
B.reagents.trans_to(src, B.amount_per_transfer_from_this)
|
||||
return
|
||||
|
||||
if(default_deconstruction_screwdriver(user, "limbgrower_panelopen", "limbgrower_idleoff", user_item))
|
||||
ui_close(user)
|
||||
@@ -180,7 +199,7 @@
|
||||
for(var/reagent_id in consumed_reagents_list)
|
||||
consumed_reagents_list[reagent_id] *= production_coefficient
|
||||
if(!reagents.has_reagent(reagent_id, consumed_reagents_list[reagent_id]))
|
||||
audible_message("<span class='notice'>\The [src] buzzes.</span>")
|
||||
audible_message("<span class='warning'>\The [src] buzzes and states \"INSUFFICENT REAGENTS\"</span>")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
|
||||
return
|
||||
|
||||
@@ -206,17 +225,13 @@
|
||||
* modified_consumed_reagents_list - the list of reagents we will consume on build, modified by the production coefficient.
|
||||
*/
|
||||
/obj/machinery/limbgrower/proc/build_item(list/modified_consumed_reagents_list)
|
||||
for(var/reagent_id in modified_consumed_reagents_list)
|
||||
if(!reagents.has_reagent(reagent_id, modified_consumed_reagents_list[reagent_id]))
|
||||
audible_message("<span class='notice'>\The [src] buzzes.</span>")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
|
||||
break
|
||||
|
||||
reagents.remove_reagent(reagent_id, modified_consumed_reagents_list[reagent_id])
|
||||
|
||||
reagent_usage(modified_consumed_reagents_list)
|
||||
var/built_typepath = being_built.build_path
|
||||
// If we have a bodypart, we need to initialize the limb on its own. Otherwise we can build it here.
|
||||
if(ispath(built_typepath, /obj/item/bodypart))
|
||||
if(ispath(built_typepath, /mob/living/carbon/human/chestonly))
|
||||
if(!build_mob_chest(built_typepath, FALSE))
|
||||
reagent_usage(modified_consumed_reagents_list, FALSE)
|
||||
else if(ispath(built_typepath, /obj/item/bodypart))
|
||||
build_limb(built_typepath)
|
||||
else if(ispath(built_typepath, /obj/item/organ/genital)) //genitals are uhh... customizable
|
||||
build_genital(built_typepath)
|
||||
@@ -227,6 +242,25 @@
|
||||
flick("limbgrower_unfill", src)
|
||||
icon_state = "limbgrower_idleoff"
|
||||
|
||||
/obj/machinery/limbgrower/proc/reagent_usage(modified_consumed_reagents_list, remove = TRUE)
|
||||
// Apparently, having a boolean in a loop is worse than doing it twice
|
||||
if(remove)
|
||||
for(var/reagent_id in modified_consumed_reagents_list)
|
||||
if(reagent_sanity_check(reagent_id, modified_consumed_reagents_list[reagent_id]))
|
||||
reagents.remove_reagent(reagent_id, modified_consumed_reagents_list[reagent_id])
|
||||
else
|
||||
for(var/reagent_id in modified_consumed_reagents_list)
|
||||
if(reagent_sanity_check(reagent_id, modified_consumed_reagents_list[reagent_id]))
|
||||
reagents.add_reagent(reagent_id, modified_consumed_reagents_list[reagent_id])
|
||||
|
||||
|
||||
/obj/machinery/limbgrower/proc/reagent_sanity_check(reagent_id, amount)
|
||||
if(reagents.has_reagent(reagent_id, amount))
|
||||
return TRUE
|
||||
audible_message("<span class='warning'>\The [src] buzzes, with a screen showing: INSUFFICENT REAGENTS</span>")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
|
||||
return FALSE
|
||||
|
||||
/*
|
||||
* The process of putting together a limb.
|
||||
* This is called from after we remove the reagents, so this proc is just initializing the limb type.
|
||||
@@ -306,6 +340,53 @@
|
||||
else
|
||||
new built_typepath(loc)
|
||||
|
||||
/obj/machinery/limbgrower/proc/build_mob_chest(built_typepath)
|
||||
// Create a mob with a chest, but nothing else
|
||||
if(!ispath(built_typepath, /mob/living/carbon/human/chestonly))
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
|
||||
visible_message(src, "Buzzes, an error screen appearing on its display.")
|
||||
return FALSE
|
||||
// Fields is from cloning, a much fuller scan, genetic_makeup_buffer is less so
|
||||
var/dna_genetics = dna_disk?.genetic_makeup_buffer
|
||||
var/dna_cloning = dna_disk?.fields
|
||||
var/datum/species/selected = GLOB.species_datums[selected_category]
|
||||
var/mob/living/carbon/human/chestonly/C = new(loc)
|
||||
C.real_name = length(dna_genetics) ? dna_genetics["name"] : "Synthetic Humanoid #[rand(10000, 99999)]"
|
||||
if(length(dna_cloning))
|
||||
C.hardset_dna(dna_cloning["UI"], dna_cloning["SE"], dna_cloning["name"], dna_cloning["blood_type"], dna_cloning["mrace"], dna_cloning["features"])
|
||||
else if(length(dna_genetics))
|
||||
C.hardset_dna(dna_genetics["UI"], null, dna_genetics["name"], dna_genetics["blood_type"])
|
||||
else
|
||||
C.real_name = "Synthetic Humanoid #[rand(10000, 99999)]"
|
||||
C.hair_style = "bald"
|
||||
C.skin_tone = "albino"
|
||||
C.set_species(selected)
|
||||
C.set_resting(TRUE, TRUE)
|
||||
// Don't want to cause it to deathgasp..
|
||||
C.stat = DEAD
|
||||
C.adjustOxyLoss(200)
|
||||
// Limb replacement causes toxloss, which can cause too much suffering for the doctor that I don't want
|
||||
C.adjustCloneLoss(45)
|
||||
C.med_hud_set_status()
|
||||
C.med_hud_set_health()
|
||||
C.underwear = "Nude"
|
||||
C.undershirt = "Nude"
|
||||
C.saved_underwear = ""
|
||||
C.saved_undershirt = ""
|
||||
|
||||
// Just enough to start reviving them, I hope
|
||||
C.blood_volume = BLOOD_VOLUME_SURVIVE
|
||||
// At some point, make a way to deal with species regenerate_organs
|
||||
// Remove all the organs
|
||||
for(var/organ in C.internal_organs)
|
||||
var/obj/item/organ/O = organ
|
||||
O.Remove(organ)
|
||||
C.update_body(TRUE)
|
||||
C.update_hair()
|
||||
C.update_body_parts()
|
||||
C.update_appearance()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/limbgrower/RefreshParts()
|
||||
reagents.maximum_volume = 0
|
||||
for(var/obj/item/reagent_containers/glass/our_beaker in component_parts)
|
||||
|
||||
@@ -351,7 +351,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
return
|
||||
if(anchored)
|
||||
return
|
||||
if(loc == user && current_equipped_slot && current_equipped_slot != SLOT_HANDS)
|
||||
if(loc == user && current_equipped_slot && current_equipped_slot != ITEM_SLOT_HANDS)
|
||||
if(current_equipped_slot in user.check_obscured_slots())
|
||||
to_chat(user, "<span class='warning'>You are unable to unequip that while wearing other garments over it!</span>")
|
||||
return FALSE
|
||||
@@ -416,7 +416,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
return
|
||||
if(anchored)
|
||||
return
|
||||
if(loc == user && current_equipped_slot && current_equipped_slot != SLOT_HANDS)
|
||||
if(loc == user && current_equipped_slot && current_equipped_slot != ITEM_SLOT_HANDS)
|
||||
if(current_equipped_slot in user.check_obscured_slots())
|
||||
to_chat(user, "<span class='warning'>You are unable to unequip that while wearing other garments over it!</span>")
|
||||
return FALSE
|
||||
@@ -568,7 +568,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
|
||||
//sometimes we only want to grant the item's action if it's equipped in a specific slot.
|
||||
/obj/item/proc/item_action_slot_check(slot, mob/user, datum/action/A)
|
||||
if(slot == SLOT_IN_BACKPACK || slot == SLOT_LEGCUFFED) //these aren't true slots, so avoid granting actions there
|
||||
if(slot == ITEM_SLOT_BACKPACK || slot == ITEM_SLOT_LEGCUFFED) //these aren't true slots, so avoid granting actions there
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -817,7 +817,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
if(ismob(location))
|
||||
var/mob/M = location
|
||||
var/success = FALSE
|
||||
if(src == M.get_item_by_slot(SLOT_WEAR_MASK))
|
||||
if(src == M.get_item_by_slot(ITEM_SLOT_MASK))
|
||||
success = TRUE
|
||||
if(success)
|
||||
location = get_turf(M)
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
user.put_in_hands(PA)
|
||||
|
||||
/obj/item/chrono_eraser/item_action_slot_check(slot, mob/user, datum/action/A)
|
||||
if(slot == SLOT_BACK)
|
||||
if(slot == ITEM_SLOT_BACK)
|
||||
return 1
|
||||
|
||||
/obj/item/gun/energy/chrono_gun
|
||||
|
||||
@@ -89,7 +89,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
..()
|
||||
|
||||
/obj/item/proc/help_light_cig(mob/living/M)
|
||||
var/mask_item = M.get_item_by_slot(SLOT_WEAR_MASK)
|
||||
var/mask_item = M.get_item_by_slot(ITEM_SLOT_MASK)
|
||||
if(istype(mask_item, /obj/item/clothing/mask/cigarette))
|
||||
return mask_item
|
||||
|
||||
@@ -130,7 +130,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
reagents.add_reagent_list(list_reagents)
|
||||
if(starts_lit)
|
||||
light()
|
||||
AddComponent(/datum/component/knockoff,90,list(BODY_ZONE_PRECISE_MOUTH),list(SLOT_WEAR_MASK))//90% to knock off when wearing a mask
|
||||
AddComponent(/datum/component/knockoff,90,list(BODY_ZONE_PRECISE_MOUTH),list(ITEM_SLOT_MASK))//90% to knock off when wearing a mask
|
||||
|
||||
/obj/item/clothing/mask/cigarette/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
@@ -819,7 +819,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
|
||||
/obj/item/clothing/mask/vape/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if(slot == SLOT_WEAR_MASK)
|
||||
if(slot == ITEM_SLOT_MASK)
|
||||
if(!screw)
|
||||
to_chat(user, "<span class='notice'>You start puffing on the vape.</span>")
|
||||
reagents.reagents_holder_flags &= ~(NO_REACT)
|
||||
@@ -830,7 +830,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
/obj/item/clothing/mask/vape/dropped(mob/user)
|
||||
. = ..()
|
||||
var/mob/living/carbon/C = user
|
||||
if(C.get_item_by_slot(SLOT_WEAR_MASK) == src)
|
||||
if(C.get_item_by_slot(ITEM_SLOT_MASK) == src)
|
||||
reagents.reagents_holder_flags |= NO_REACT
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
|
||||
@@ -80,13 +80,13 @@
|
||||
/obj/item/defibrillator/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(loc == user)
|
||||
if(slot_flags == ITEM_SLOT_BACK)
|
||||
if(user.get_item_by_slot(SLOT_BACK) == src)
|
||||
if(user.get_item_by_slot(ITEM_SLOT_BACK) == src)
|
||||
ui_action_click()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Put the defibrillator on your back first!</span>")
|
||||
|
||||
else if(slot_flags == ITEM_SLOT_BELT)
|
||||
if(user.get_item_by_slot(SLOT_BELT) == src)
|
||||
if(user.get_item_by_slot(ITEM_SLOT_BELT) == src)
|
||||
ui_action_click()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Strap the defibrillator's belt on first!</span>")
|
||||
@@ -182,7 +182,7 @@
|
||||
|
||||
/obj/item/defibrillator/equipped(mob/user, slot)
|
||||
..()
|
||||
if((slot_flags == ITEM_SLOT_BACK && slot != SLOT_BACK) || (slot_flags == ITEM_SLOT_BELT && slot != SLOT_BELT))
|
||||
if((slot_flags == ITEM_SLOT_BACK && slot != ITEM_SLOT_BACK) || (slot_flags == ITEM_SLOT_BELT && slot != ITEM_SLOT_BELT))
|
||||
remove_paddles(user)
|
||||
update_power()
|
||||
|
||||
@@ -423,7 +423,7 @@
|
||||
if((!req_defib && grab_ghost) || (req_defib && defib.grab_ghost))
|
||||
H.notify_ghost_cloning("Your heart is being defibrillated!")
|
||||
H.grab_ghost() // Shove them back in their body.
|
||||
else if(H.can_defib())
|
||||
else if(H.can_revive())
|
||||
H.notify_ghost_cloning("Your heart is being defibrillated. Re-enter your corpse if you want to be revived!", source = src)
|
||||
|
||||
do_help(H, user)
|
||||
|
||||
@@ -369,6 +369,10 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
dat += "<li><a href='byond://?src=[REF(src)];choice=Toggle Door'>[PDAIMG(rdoor)]Toggle Remote Door</a></li>"
|
||||
if (cartridge.access & CART_DRONEPHONE)
|
||||
dat += "<li><a href='byond://?src=[REF(src)];choice=Drone Phone'>[PDAIMG(dronephone)]Drone Phone</a></li>"
|
||||
if (cartridge.access & CART_BARTENDER)
|
||||
dat += "<li><a href='byond://?src=[REF(src)];choice=Drink Recipe Browser'>[PDAIMG(bucket)]Drink Recipe Browser</a></li>"
|
||||
if (cartridge.access & CART_CHEMISTRY)
|
||||
dat += "<li><a href='byond://?src=[REF(src)];choice=Chemistry Recipe Browser'>[PDAIMG(bucket)]Chemistry Recipe Browser</a></li>"
|
||||
dat += "<li><a href='byond://?src=[REF(src)];choice=3'>[PDAIMG(atmos)]Atmospheric Scan</a></li>"
|
||||
dat += "<li><a href='byond://?src=[REF(src)];choice=Light'>[PDAIMG(flashlight)][fon ? "Disable" : "Enable"] Flashlight</a></li>"
|
||||
if (pai)
|
||||
@@ -705,6 +709,16 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
if(T)
|
||||
pai.forceMove(T)
|
||||
|
||||
//DRINK RECIPE BROWSER=============================
|
||||
if("Drink Recipe Browser")
|
||||
if(cartridge && cartridge.access & CART_BARTENDER)
|
||||
recipe_search(U, GLOB.drink_reactions_list)
|
||||
|
||||
//CHEMISTRY RECIPE BROWSER
|
||||
if("Chemistry Recipe Browser")
|
||||
if(cartridge && cartridge.access & CART_CHEMISTRY)
|
||||
recipe_search(U, GLOB.normalized_chemical_reactions_list)
|
||||
|
||||
//LINK FUNCTIONS===================================
|
||||
|
||||
else//Cartridge menu linking
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
/obj/item/pda/bar
|
||||
name = "bartender PDA"
|
||||
icon_state = "pda-bartender"
|
||||
default_cartridge = /obj/item/cartridge/bartender
|
||||
inserted_item = /obj/item/pen/fountain
|
||||
|
||||
/obj/item/pda/atmos
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#define CART_QUARTERMASTER (1<<12)
|
||||
#define CART_HYDROPONICS (1<<13)
|
||||
#define CART_DRONEPHONE (1<<14)
|
||||
#define CART_BARTENDER (1<<15)
|
||||
#define CART_CHEMISTRY (1<<16)
|
||||
|
||||
|
||||
/obj/item/cartridge
|
||||
@@ -77,7 +79,7 @@
|
||||
/obj/item/cartridge/chemistry
|
||||
name = "\improper ChemWhiz cartridge"
|
||||
icon_state = "cart-chem"
|
||||
access = CART_REAGENT_SCANNER
|
||||
access = CART_REAGENT_SCANNER | CART_CHEMISTRY
|
||||
bot_access_flags = MED_BOT
|
||||
|
||||
/obj/item/cartridge/security
|
||||
@@ -190,6 +192,12 @@
|
||||
bot_access_flags = SEC_BOT | MULE_BOT | FLOOR_BOT | CLEAN_BOT | MED_BOT | FIRE_BOT
|
||||
spam_enabled = 1
|
||||
|
||||
/obj/item/cartridge/bartender
|
||||
name = "\improper B.O.O.Z.E cartridge"
|
||||
desc = "Now with 12% alcohol!"
|
||||
icon_state = "cart-bar"
|
||||
access = CART_BARTENDER
|
||||
|
||||
/obj/item/cartridge/captain/New()
|
||||
..()
|
||||
radio = new(src)
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
/obj/item/megaphone/equipped(mob/M, slot)
|
||||
. = ..()
|
||||
if (slot == SLOT_HANDS)
|
||||
if (slot == ITEM_SLOT_HANDS)
|
||||
RegisterSignal(M, COMSIG_MOB_SAY, .proc/handle_speech)
|
||||
else
|
||||
UnregisterSignal(M, COMSIG_MOB_SAY)
|
||||
|
||||
@@ -156,7 +156,7 @@
|
||||
category = list("hacked", "Misc")
|
||||
|
||||
/obj/item/electropack/shockcollar/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(loc == user && user.get_item_by_slot(SLOT_NECK))
|
||||
if(loc == user && user.get_item_by_slot(ITEM_SLOT_NECK))
|
||||
to_chat(user, "<span class='warning'>The collar is fastened tight! You'll need help taking this off!</span>")
|
||||
return
|
||||
return ..()
|
||||
@@ -167,7 +167,7 @@
|
||||
|
||||
if(isliving(loc) && on) //the "on" arg is currently useless
|
||||
var/mob/living/L = loc
|
||||
if(!L.get_item_by_slot(SLOT_NECK)) //**properly** stops pocket shockers
|
||||
if(!L.get_item_by_slot(ITEM_SLOT_NECK)) //**properly** stops pocket shockers
|
||||
return
|
||||
if(shock_cooldown == TRUE)
|
||||
return
|
||||
|
||||
@@ -56,7 +56,7 @@ GLOBAL_LIST_INIT(channel_tokens, list(
|
||||
/obj/item/radio/headset/ComponentInitialize()
|
||||
. = ..()
|
||||
if (bowman)
|
||||
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
|
||||
AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS))
|
||||
|
||||
/obj/item/radio/headset/Initialize()
|
||||
. = ..()
|
||||
@@ -373,4 +373,4 @@ GLOBAL_LIST_INIT(channel_tokens, list(
|
||||
name = replacetext(name,"headset", "bowman headset")
|
||||
desc = "[desc] Protects ears from flashbangs."
|
||||
bowman = TRUE
|
||||
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
|
||||
AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS))
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
/obj/item/reverse_bear_trap/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
if(C.get_item_by_slot(SLOT_HEAD) == src)
|
||||
if(C.get_item_by_slot(ITEM_SLOT_HEAD) == src)
|
||||
if(HAS_TRAIT_FROM(src, TRAIT_NODROP, REVERSE_BEAR_TRAP_TRAIT) && !struggling)
|
||||
struggling = TRUE
|
||||
var/fear_string
|
||||
@@ -82,26 +82,26 @@
|
||||
..()
|
||||
|
||||
/obj/item/reverse_bear_trap/attack(mob/living/target, mob/living/user)
|
||||
if(target.get_item_by_slot(SLOT_HEAD))
|
||||
if(target.get_item_by_slot(ITEM_SLOT_HEAD))
|
||||
to_chat(user, "<span class='warning'>Remove [target.p_their()] headgear first!</span>")
|
||||
return
|
||||
target.visible_message("<span class='warning'>[user] starts forcing [src] onto [target]'s head!</span>", \
|
||||
"<span class='userdanger'>[target] starts forcing [src] onto your head!</span>", "<i>You hear clanking.</i>")
|
||||
to_chat(user, "<span class='danger'>You start forcing [src] onto [target]'s head...</span>")
|
||||
if(!do_after(user, 30, target = target) || target.get_item_by_slot(SLOT_HEAD))
|
||||
if(!do_after(user, 30, target = target) || target.get_item_by_slot(ITEM_SLOT_HEAD))
|
||||
return
|
||||
target.visible_message("<span class='warning'>[user] forces and locks [src] onto [target]'s head!</span>", \
|
||||
"<span class='userdanger'>[target] locks [src] onto your head!</span>", "<i>You hear a click, and then a timer ticking down.</i>")
|
||||
to_chat(user, "<span class='danger'>You force [src] onto [target]'s head and click the padlock shut.</span>")
|
||||
user.dropItemToGround(src)
|
||||
target.equip_to_slot_if_possible(src, SLOT_HEAD)
|
||||
target.equip_to_slot_if_possible(src, ITEM_SLOT_HEAD)
|
||||
arm()
|
||||
notify_ghosts("[user] put a reverse bear trap on [target]!", source = src, action = NOTIFY_ORBIT, ghost_sound = 'sound/machines/beep.ogg')
|
||||
|
||||
/obj/item/reverse_bear_trap/proc/snap()
|
||||
reset()
|
||||
var/mob/living/carbon/human/H = loc
|
||||
if(!istype(H) || H.get_item_by_slot(SLOT_HEAD) != src)
|
||||
if(!istype(H) || H.get_item_by_slot(ITEM_SLOT_HEAD) != src)
|
||||
visible_message("<span class='warning'>[src]'s jaws snap open with an ear-piercing crack!</span>")
|
||||
playsound(src, 'sound/effects/snap.ogg', 75, TRUE)
|
||||
else
|
||||
|
||||
@@ -380,6 +380,8 @@ GENETICS SCANNER
|
||||
mutant = TRUE
|
||||
else if (S.mutantstomach != initial(S.mutantstomach))
|
||||
mutant = TRUE
|
||||
else if (S.flying_species != initial(S.flying_species))
|
||||
mutant = TRUE
|
||||
|
||||
msg += "\t<span class='info'>Reported Species: [H.spec_trait_examine_font()][H.dna.custom_species ? H.dna.custom_species : S.name]</font></span>\n"
|
||||
msg += "\t<span class='info'>Base Species: [H.spec_trait_examine_font()][S.name]</font></span>\n"
|
||||
@@ -434,7 +436,7 @@ GENETICS SCANNER
|
||||
if(R)
|
||||
blood_type = R.name
|
||||
|
||||
|
||||
|
||||
if((C.scan_blood_volume() + C.integrating_blood) <= (BLOOD_VOLUME_SAFE * C.blood_ratio) && (C.scan_blood_volume() + C.integrating_blood) > (BLOOD_VOLUME_OKAY*C.blood_ratio))
|
||||
msg += "<span class='danger'>LOW [HAS_TRAIT(C, TRAIT_ROBOTIC_ORGANISM) ? "coolant" : "blood"] level [blood_percent] %, [C.scan_blood_volume()] cl[C.integrating_blood? ", with [integrated_blood_percent] % of it integrating, [C.integrating_blood] cl " : ""].</span> <span class='info'>type: [blood_type]</span>\n"
|
||||
else if((C.scan_blood_volume() + C.integrating_blood) <= (BLOOD_VOLUME_OKAY * C.blood_ratio))
|
||||
|
||||
@@ -208,7 +208,7 @@ effective or pretty fucking useless.
|
||||
actions_types = list(/datum/action/item_action/toggle)
|
||||
|
||||
/obj/item/shadowcloak/ui_action_click(mob/user)
|
||||
if(user.get_item_by_slot(SLOT_BELT) == src)
|
||||
if(user.get_item_by_slot(ITEM_SLOT_BELT) == src)
|
||||
if(!on)
|
||||
Activate(usr)
|
||||
else
|
||||
@@ -216,7 +216,7 @@ effective or pretty fucking useless.
|
||||
return
|
||||
|
||||
/obj/item/shadowcloak/item_action_slot_check(slot, mob/user, datum/action/A)
|
||||
if(slot == SLOT_BELT)
|
||||
if(slot == ITEM_SLOT_BELT)
|
||||
return 1
|
||||
|
||||
/obj/item/shadowcloak/proc/Activate(mob/living/carbon/human/user)
|
||||
@@ -238,11 +238,11 @@ effective or pretty fucking useless.
|
||||
|
||||
/obj/item/shadowcloak/dropped(mob/user)
|
||||
..()
|
||||
if(user && user.get_item_by_slot(SLOT_BELT) != src)
|
||||
if(user && user.get_item_by_slot(ITEM_SLOT_BELT) != src)
|
||||
Deactivate()
|
||||
|
||||
/obj/item/shadowcloak/process()
|
||||
if(user.get_item_by_slot(SLOT_BELT) != src)
|
||||
if(user.get_item_by_slot(ITEM_SLOT_BELT) != src)
|
||||
Deactivate()
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// 1) Tennis balls, lines 39 - 99
|
||||
// 2) Chew bones, lines 101 - 138
|
||||
// 3) Frisbee, lines 140 - 166
|
||||
*/
|
||||
*/
|
||||
|
||||
/obj/item/toy/fluff
|
||||
name = "Fluff Item"
|
||||
|
||||
@@ -336,7 +336,7 @@
|
||||
var/obj/item/clothing/magichead = new /obj/item/clothing/mask/horsehead/cursed(user.drop_location())
|
||||
if(!user.dropItemToGround(user.wear_mask))
|
||||
qdel(user.wear_mask)
|
||||
user.equip_to_slot_if_possible(magichead, SLOT_WEAR_MASK, TRUE, TRUE)
|
||||
user.equip_to_slot_if_possible(magichead, ITEM_SLOT_MASK, TRUE, TRUE)
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user,"<span class='notice'>I say thee neigh</span>") //It still lives here
|
||||
|
||||
@@ -189,5 +189,7 @@
|
||||
return FALSE
|
||||
brainwash(C, objective)
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.")
|
||||
user.log_message("has brainwashed [key_name(C)] with the objective '[objective]' using \the [src]", LOG_ATTACK)
|
||||
C.log_message("has been brainwashed with the objective '[objective]' by [key_name(user)] using \the [src]", LOG_VICTIM, log_globally = FALSE)
|
||||
log_game("[key_name(user)] brainwashed [key_name(C)] with objective '[objective]'.")
|
||||
return TRUE
|
||||
|
||||
@@ -188,7 +188,7 @@
|
||||
icon_state = "inducer-combat"
|
||||
item_state = "inducer-combat"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
slot_flags = SLOT_BELT
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
desc = "A tool for inductively charging internal power cells. This one has been modified and upgraded to be able to charge into guns as well as normal electronics."
|
||||
cell_type = /obj/item/stock_parts/cell/hyper
|
||||
powertransfer = 1300
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user