-
Posts
413 -
Joined
-
Last visited
Content Type
Profiles
Forums
Events
Gallery
Everything posted by GreenBoi
-
Project Anabasis Development Diary #3 - The Vision of it All
GreenBoi replied to MattAtlas's topic in General Announcements
I think you're simultaneously underestimating corporate utility and overestimating their authority. Corporations are still corporations with a lot of useful resources and tools that'd be worth bargaining for. The Blood Diamond's Tier 3, the good one you'll want to work to stay around, is supposed to be equivalent to standard retail equipment. Getting any trace of that from corporate contracts would likely be amazing in-universe. And this is where the corporations' waning influence comes in, you could feasibly do this under their nose and bribe or use some leverage to keep them from retaliating. Corporations would now be at the position where they have just enough resources to be targets of interest, but not enough to deal with everything. For wreckages, they could allow salvage rights to incentivize plunderers to make official deals with them, properly logging sites and assets rather than just being entirely in the dark while they lose stuff. Concessions and deals like this are very realistic, I basically just described what British pirates were for the government as privateers against enemies- officializing an activity and weaponizing it to aid you over hurting. -
This is being implemented with the following PR: https://github.com/Aurorastation/Aurora.3/pull/22772, the option will be available in Character Setup as "Custom Model" As desired, the true frame is preserved at the end of the sentence. Shells that opt into using it are also necessarily revealed.
-
Wildkins' guide is good at telling you to set up your first PR and even test servers, but it doesn't tell you much about actual coding and other ways to contribute are currently unfinished. I've been programming for exactly [52 when I posted this, + 31 to edit its main guide to completion] days, that's under two months, and I've made seven successful PRs plus a few more yet to be uploaded. They weren't super-complicated, but I did add cool stuff, and the coolest PRs I learned to make within my first 10 days. Coding contributions are the ultimate lifeblood of the server, so I intend to comprehensively teach the foundations so anyone can learn within ten days. I've been told it's better to learn programming in another, bigger language and then return to apply fundamentals to DM, but that's an entire extra layer of friction for beginners to hear. For the record, programming languages share a lot of fundamental concepts so it's easier to swap to another than you think, but that still feels like huge overkill when you just want a simple PR done, so I'll do that part for you. The "lazy" part of this guide is the fact I don't want you to worry about more than necessary for functional DM code. You will eventually and naturally learn smart practices, it's literally the job of maintainers to tell you so the server doesn't break. There will be quick references you can Ctrl+F in this guide for understanding particular systems, they'll be focused on the logic so even if the code becomes out-of-date, the skill is still good. Just so it's in this post, here's a quick refresher on forking and setting up a local repository, and GitHub terminology. This is the Table of Contents for the sections of this post, note that the actual coding guide is pretty short because the fundamentals aren't that complex. Just give 30 minutes reading and you'll be able to break down and write most code. If you ever need to learn something more specific, check a Quickref for directions. Now, for BYOND CODING BASICS 1/3 : Objects, Overriding, Procedures The main language for SS13 is Dream Maker, its official documentation is here and a mostly-fine source for understanding in-built parts of the language. To understand DM and minimize structural problems or frustration, you NEED to understand Object-Oriented Programming. OOP relies on encapsulation and inheritance. An object is just a recognized bundle of data, variables are specific pieces of data, encapsulation is the bundling of this relevant data together in one object and inheritance is when related child objects share data from their parents. Children can override and change data from their parents, and freely declare entirely new data for themselves which will also be inherited by any children they have. In VSCode, you can right-click/Go -> Go to Definition (F12) and quickly find the variable's declaration. In BYOND, there are four main objects which will be familiar to you: Area, zones like what APCs grant power to; Turf, the flooring below you; Obj, physical items and structures; and Mob, short for mobile object, which covers players & creatures. Atom is a special object which is the ancestor to all mappable objects (areas, turfs, objs, mobs...hey, see what they did?), and Datum is the parent to effectively all types, it's mostly used to hold "pure information" like your character's DNA in-game, xenoarch artifact effects, or computer programs; datum is always the implied parent of types with seemingly no parent (ex: "plushie" alone is actually "/datum/plushie") Comprehension Checkpoint 1/2 - Can you figure out the relationship between the objs inside the spoiler, and why? Objects alone are just bundles of data. For anything to actually happen like even changing a set value (without making a child), we use procs or procedures, known generally as functions in programming. Objects are like stations and procs are like trains, neither does anything alone, and must connect. A proc is predefined data attached to an object with "type/proc/procname()" and simply does stuff to data when called; that can be directly changing the data, calling other procs, or simply retrieving what the data is. Like objects, procs inherit from their parents and get inherited by all children, where they're formatted as just "type/procname()". They MUST be called to do anything, and any new variable declared inside a proc only exists until it ends. The entire game is legitimately just a bunch of procs triggering each other, with objects storing long-term data. Not kidding, VSCode allows you to pause all code running in a few ways, and you can clearly see stops usually pause the call stacks from the Master Controller's Loop() proc...it's truly just procedures triggering each other all the way down. The new() proc is in-built for all types, it's what general programming calls a constructor because it constructs an actual instance of the object into the game world with its own vars at the location sent as the first argument. Without calling it, objects are just kind of floating data templates. new()'s effect on a particular type can be defined through New(). The custom troll() proc will be inherited by all objs, and changes their in-built name variable to "Trolled!" Calling procs is as simple as writing its name, so this could be called through troll() obj/New() object_id = total_objects total_objects += 1 /obj/proc/troll() name = "Trolled!" Procedures have args or arguments, also called parameters, that can go in their parentheses and allow data to be passed in and out as named variables. Input order corresponds to arg order, however an argument's value can be specified out-of-order. Arguments can have default values through simply being assigned one in the proc declaration, they can also have their type written out to accept only values under that. /obj/proc/vandalize(newname = name, newdesc = "Vandalized!") name = "[newname]" desc = newdesc With this proc definition, you can use vandalize("Cool Name", "Cool Desc") to set an obj's name and desc to the respective text strings. vandalize(newdesc = "Cool Desc") would skip the first argument and just set a new description. Because newname has a default assigned value, not inputting it while calling the proc just results in the name staying the same. If there weren't a default value, newname would be equal to null which naturally blanks out the name. The brackets in quotes are a DM-specific feature called "embeds", which lets you automatically text-stringify a variable or even proc result; that's actually very convenient and well-designed compared to other programming languages. It's not necessary for the example situation, but it's good to know about that as some stuff like name and desc SHOULD be text-only values on the actual server. Taking it one step further, DM also has text macros like \the and \a which automatically input the word when it'd work for a sentence...usually right. Comprehension Checkpoint 2/2 - What is the mistake in this proc? Like variables in objects, procs can also be overridden in children. Doing this gives it an entirely new function, which can be handy for specific interactions, but you will probably want to instead call the parent proc. The present return value of a proc is referenced with a period . character, and ..() calls the parent, so ". = ..()" means "assign the value of the parent proc to the current one." Extending the parent proc in this example makes canine plushies uniquely get their number_of_legs lowered by 1 while also getting a changed desc. /obj/plushie/canine/vandalize() . = ..() number_of_legs -= 1 You can keep extending forever to always add stuff, if you want to. This is how mechanics hints in examines work on the server, they're a separate inherited proc that extends the parent to get added onto the examine. Arguments themselves can also be overridden, adding in new ones or even removing some; never remove args, it's confusing. The Takeaway 1. Objects cannot change values or interact without using procs. 2. Procs cannot affect anything permanently without using pre-existing objects. 3. Variables not declared with "var" and procs not using "/proc/procname()" are inherited from parents. 4. Go to Definition can be used to learn context and purpose, especially when the inherited proc is also calling its parent. Alternatively, search for "var/" or "/proc/" Procs can actually be used before they're defined, unlike objects, because the definition is just instruction for what to do when called. BYOND CODING BASICS 2/3: Scope and Access Prior examples assumed you're using a variable or proc from the same object it's attached it, but this is commonly not the case. Related to inheritance is the concept of scope, which affects what data you're allowed to modify and what they can be identified as. Scope flows downwards and only data from the current scope or higher can be modified. Variables, objects, and proc name declarations are unique for their scope and all beneath it. Using the vandalize() example: because that's attached to /obj/ itself, /obj/plushie/proc/vandalize() is invalid because it'd compete within the scope. To access data outside the current scope, you use the . operator after their name, which can be chained to go down several layers of variables if necessary. Knowing what and when you can access data is a a huge part of structuring code, do not overlook it. vandalize() is a purely internal proc right now that can only be used by the object itself, so for players to ever interact with it, you'd need to actually use another proc that either passes to the object's scope or calls object.vandalize() The most specific scope is with a reference, which is the exact computer memory address of an individual object- so, completely unique and constrained to that particular instance. Holding references is necessary to affect an instance of anything, they are the keys to extending access and different methods should be used when situations arise. Lists are the most obvious way besides single-value variables, you can hold however-many you need for later access and if that list is part of an object then having access to the object extends access to not only the list, not only access to references in it, but also any held references within those references. Lists are pretty great and make up a common method of storing important references at the high-level, it's even possible to have lists of lists or multi-dimensional lists where each item holds lists with several other lists; obviously, avoid excessive lists that hold so much extra stuff. "contents" is a convenient, in-built, atom-level variable that lists everything contained by an object. List items can be accessed through their index number in brackets if you know it, which count from 1 (ex: list_name[1]) in Dream Maker (most languages count from 0), or found with a for loop. For loops iterate over a fixed range, literally performing its instructions for each instance; they're the most consistent way to affect multiple objects or search for a particular one. A for loop can be declared a few different ways, but should probably look like these as they're most readable and straightforward: for(var/thing in list_of_stuff) // Form 1: Assign from list if(istype(thing, /obj/plushie)) thing.name = "Stuffed Plush" for(var/obj/plushie/plush in list) // Form 2: Filter in list for(var/num in 1 to 10) // Form 3: Increment over range. Bonus: procs that return lists are also valid for any of these. // If you want to check for something NOT in a list, it HAS to be done as if(!(thing in list_off)) because of BYOND's operator priorities. Form 1 for loops assigns each item in the list to the lefthand variable "thing", which may then be used to affect the item's variables. Form 2 for loops, however, typecast the variable to filter for that type in the list, which is useful for more specific internal procs or variables. Typecasting is a general thing that can be done outside lists too. Note that in the syntax of Dream Maker, the latest type after the last slash is always the variable name, so "plush" is just the instance variable name for anything under the path /obj/plushie, this also naturally includes child types. The variables declared in a for loop only exists until its end, but you should probably still keep its name distinct from its parent type for the sake of clarity. Form 3 allows incrementing over numerical ranges, there can even be variables in place of the numbers for an adjustable loop. To filter for multiple objects, you can use Form 1 with an istype() check as shown above. If you're looking for just one object or the first instance, you can break out of the loop to end it early; alternatively, you may filter out objects you don't want using continue to skip it in the loop. There's also the associative list, sometimes generally known as dictionaries, which has each item as a unique key paired to an inner value. Associative lists are useful to easily retrieve data without a for loop, it's as simple as using the key to access the value: var/list_of_stuff[0] // Declare 0-item list list_of_stuff("Plush Dog" = /obj/plushie/dog) // parentheses format is a method of declaration list_of_stuff["Plush Wolf"] = /obj/plushie/canine/wolf // brackets format here is equal to .Add("keyname" = value) // Now, using either keys list_of_stuff["Plush Dog"] and list_of_stuff["Plush Wolf"] would automatically link to the associated value in any context In some cases, for really tedious and repetitive actions, a while loop can be desirable. Where for loops iterate over a finite range, while loops can iterate infinitely, so it's very important you have proper checks. Verbs are a part of Dream Maker declared with /verb/ you're definitely familiar with from play, they show up clickable on panels and are typable in the command bar working functionally identical to procs. Where procs are only used when called in code, declared verbs are usable live whenever a player has access to its source, that is their effective scope: this is handy for cases of range-limited obj verbs through set src, but there's no way to restrict having them for only specific instances of an object. In order to restrict verbs to certain states or specific instances, you'll want them declared as procs for the constrained access and then added to the specific atom's verbs list variable to make it display like a normal verb. COMPREHENSION CHECKPOINT 1/1 - Which verb is properly restricted? The broadest scope is the global scope, variables and objects there are accessible by everything else in code. You should avoid declaring new globals when unnecessary because they all take up memory, but if you must then make sure the names are specific and recognizable so it's hard to accidentally access them or cause conflicts. Global values shouldn't be casually modified and situations where you'd want to do so can always instead use a new local variable which will limit unintended side-effects. The Takeaway 1. Scope determines access to values and flows down like inheritance, so you can only access data from the current scope or higher. The . operator is used to access data outside the current scope. 2. References are the exact instance of an object, necessary for specific targeting, and can extend access to further object references held inside. 3. Lists can store many values in one place, and associative lists can make it easy to retrieve them. 4. For loops can iterate, search, or filter through any list of values. BYOND CODING BASICS 3/3: Syntax, Assignment, and Macros Now that you know what objects are, and where or when to access them, you just need to know how things are organized to start coding for real. In Dream Maker, all code gets written into .dm files, sprites or icons go into .dmi files, and maps are in .dmm files. Code in any .dm file can access and modify code in others, so these files are purely organizational and in the actual codebase, you'll find some objects are defined in entirely different .dm files from where they're used to organize all relevant definitions in one place. If adding a new file, know that you have to #include its file path in aurorastation.dme so it compiles with the others. Coding really is a language and just like any language, there's rules for sentence logic and multiple ways to accomplish the same thing. /obj/plushie // This is the most common path syntax you'll recognize, it's used for a good reason. name = "relaxing plush" /obj/plushie/canine/var/number_of_legs = 4 // This is valid path syntax in DM, but it's less readable for multiple variables obj // This is also technically-valid syntax, but it's even less readable and impossible to search for plushie dog name = "cute dog" The double forward slashes mark comments: nothing after them is executed as code. Real comments are left behind to explain complex or less-intuitive code blocks. Multi-line ones can be done with /* and */, you can also leave useful DMDoc comments that appear as a tooltip when hovering over an object; read about that in the relevant quickreference. DM allows both single forward slashes and tab indentations for defining new type paths, but it's better for readability and searchability to use the former over the latter. The only exception is with indenting variables, like shown /obj/plushie's name variable. Code is otherwise structured around operators, which modify values, and procs, which facilitate that. Trying to redefine a set value outside a proc, or without overriding it under a new type, will conflict the code compiler and count as a duplicate definition of the same thing. The = sign is the operator used to define stored values, it assigns whatever is the result of the right side to be stored in the left. A similar operator is ==, which is what's used for "is equal to" checks common for both mathematical (+, -, /, *, %, <, >, <=, >=) and logical operations (!, ||, &&, ?). Logical operators are conditional checks that allow further control over code. They're almost always paired with if-statements, which you've seen before! The logic of an if-statement is simple: if the argument within the parentheses is true, then the code indented under gets executed. The logical operators are straightforward, but have their little caveats, though these ones are a general programming thing than DM-specific. var/a // No defined value means it's equal to null var/b = 2 var/c = "By the way, " \ + "this is you do multi-line text. It's useful for code readability." \ + "The backslashes ignore what would be a line-break, and the pluses kind of stitch together the quotes, but they're not necessary \ if you just keep it at one pair of quotes like this." /proc/FlipValue() if(!a || a) // || is the or operator, it stops at the first true value from left to right and skips everything after. ! is the not operator, it inverts true/falseness. a = !a b += 1 /proc/HasValue() if((a && b) || a != null) // && is the and operator, it stops at the first false value. != means "is not equal to" b -= 1 // When procs are used for && checks, they will still execute even if the check doesn't. /proc/GetValue() return a ? a : b // ? is the ternary operator, outputs value after ? sign when condition is true, value after colon when false All the logical operators have something to do with true-falseness because the root logic for all programming is binary 1s (truth) and 0s (falseness), also known as Booleans. Null and empty text strings also implicitly count as false, which makes checking values very convenient. There's also the bitwise operators (&, |, ^, ~) that get used specifically for bitflags, which are effectively multiple booleans stacked in one variable for memory optimization. You can learn more about them in the What Are Bitflags? Quickref. Compound operations like += and -= just save you time and are possible for all operators, being equal to "variable = variable + value" and so on for the other signs. ?. and ?[] are condensed ternary operators which can be used to conditionally access variables and indexes that aren't guaranteed to exist on the object. You probably shouldn't use it, but the comma is a valid operator used in some parts of the codebase which allows a range of values to be considered kind of like a list; to is an operator with a similar function that you should probably be using instead. The indented code under if-statements work like a side branch, code execution eventually returns to the same indentation level as the if once done. Similar to the ternary operator, if statements can have fallback code executed for when their condition is false with the else-if statements, which allow another condition to be checked and executed only when the prior one fails, and the plain else-statements, which always get executed at the end when the previous ifs have failed. They all follow the same indentation rule, so same-level code statements should be lining up together. COMPREHENSION CHECKPOINT 1/1 - Which if-else chain always executes code only once? Most code is controlled through a chain of various if-statements and operator use, and their effects is limited by the object's scope. How the previous sections connect should be clicking into place for you: coding is all about structure. And a feature of Dream Maker that's very convenient for structure is the #define macro, they work like substitutions for the compiler which gets them used like constant variables, or alternative procs for the macros with inputs. #define macros are globally usable by default, unless #undef is also used to remove it, then they're restricted to the file they're defined in. Proper read-only constant variables do exist, but they're only really used under specific scopes where macros can't shine. Macros are preferred over "magic numbers" which are cases in code where a proc or variable uses a number value that communicates nothing about its purpose; most macros in the codebase are typed in what's called SCREAMING_SNAKE_CASE to stand out precisely for clear communication. TRUE and FALSE are macros actually in-built into DM that can substitute 1 and 0 for variables meant to be booleans, it's a preferred convention in the codebase for readability. The actual codebase also has custom-defined time macros for SECONDS/MINUTES/HOURS/DAYS because Dream Maker's base time is in deciseconds, this also means that displaying accurate time always requires some division. Dream Maker is, at least, convenient when it comes to in-built references for ease of use. There's a few you should know that are really helpful: /* var/client - The client object is tied your connection to the server. You won't access it often unless you need an in-built var. The mob/client/ var is what you'll usually use to check for connected players src - src is a var specific to procs that just means the object the proc is attached to. It's required for an object to target itself in procs or to embed itself in text strings. Also useful for general readability or cases of a same-named external variable, "src.example = example" is clearer than "example = example" usr - usr is the mob of the player that clicked something or triggered a proc, official documentation recommends to use this with only verbs where the effect is clearest as - a keyword that lets you cast a specific return type for a proc, can be used in args. Allows procs of the casted type to be chained like castasmob()?.CastedMobProc() . - remember, . = the current return value of a proc, there will be cases where you'll want to forcibly modify this directly */ /mob/verb/MakeIanPlush() var/obj/plushie/dog/ian = new(src) //the lefthand var can be used as the implied type for new as can also cast special input types to be returned, like num for only numbers, text or message for single and multi-line strings. Final note: As they're common in some other programming languages, DM allows the ; semi-colon operator for artificial line-breaks, so you can chain multiple on one line, and {} brackets for artificial scopes like if you made tab indentations. In accordance with the codebase style, though, you shouldn't be using this syntax outside of macro definitions where they're needed. Congratulations, now you know not only the basics of Dream Maker, but the very foundations of coding! Objects define and store data, procedures access data, and operators modify data. Code structure is simply knowing and maximizing when or where different objects can access each other, that's genuinely it! Very similar to real language in that you just learn parts of a sentence, and can then grow from there. The section after this is mostly motivational and advisory for what to do when stuck or finishing up a PR, that's why it's called Direction. Before you X out or start checking the Quick References, you should understand Garbage Collection and the life cycle of variables on Aurora: Initialize() is a custom, atom-level proc we override over /New() for extra precision. Once the server's initialized, it gets called automatically whenever new is used for atoms. Obviously, always extend parent proc. Destroy() is a custom, datum-level proc we override over /Del(), also for extra precision. Obviously, parent proc should be called and returned at Destroy()'s end. qdel() is what you call to delete an object instance. Garbage Collection is the deletion of data no longer used, this usually happens automatically when an object isn't referenced by anything else. Try to ensure the relevant Destroy() definitions properly clear out newly-declared references no longer used, the alternative is memory leaks from the unwanted extra processing and hard deletes when the server tries to delete the unused data anyways inefficiently. With the codebase being open-source, there were a lot of memory leaks built up over time that (as of July 2026) have only RECENTLY been fixed through "The Lag War", with systematic analysis and PRs by primarily one committed person. These add up and caused major lag, so I'm teaching you the habit now so we don't get this again years down the line. You can have references while avoiding a hard delete using the custom WEAKREF() proc: you should read the full documentation in its .dm file, but the summary is that since weakrefs are an extra step detached, they don't slow down Garbage Collection with hard deletes. Weakrefs are also preferred for anything an object doesn't "own" and is not responsible for, a good example is the mob an exosuit is assigned to follow...it's not dependent on that, so the variable uses a weakref. Related to memory, but different from garbage collection is the concept of "expensive" code on processing or common objects, like atoms and mobs. You have some leeway with small stuff, but should be trying to make code as targeted and efficient as possible in processing. Don't forget that memory saved now is memory usable for cooler interactions later. Also don't forget to check official DM documentation to know the nuances of in-built features. The Takeaway 1. Code is written and organized in .dm files, some objects get defined in different files from where they're used to keep relevant definitions in one place. 2. Type paths can be defined through forward slashes or indentations: forward slashes that make absolute type paths are preferred for searchability, tab indents are preferred for readability in declaring variables. 3. Code is structured through operators modifying values, like = which assigns the right value into the left variable. Logical operators are conditional checks for controlling code execution with if-statements. 4. Binary TRUE (1) and FALSENESS (0) is the root logic of all programming. Null and empty text strings implicitly count as false in checks. 5. ! is the not operator, it inverts true-falseness. && checks for and stops at the first false value. != checks for if things aren't equal. ? a : b is the ternary operator, outputs a when true, b when false. 6. if-statements execute code indented under them when their condition is true, moves to else-if statements if possible when false, then finally else if those are also false. 7. src is a var meaning the object a proc is attached to. usr is the mob of the player that triggered a proc, best you only use it on verbs. client is an object tied to server connection, mob/client/ can check for a connected player 8. The left declared variable can be used as an implied type for a new assignment. 9. Initialize() is used over /New(), and Destroy() over /Del(). Call qdel() to delete object instances and override Destroy() to properly clear out references. 10. Use weakrefs for things an object doesn't own. 11. Be efficient with processing objects, and remember to refresh yourself on documentation DIRECTION 1/4: It's All Illusory An important part about programming to understand is it being smoke and mirrors, interactions are all varyingly-convincing illusions. I realized this in one of my first PRs, touching on the psionic ability Commune. It achieves its effect of saving a snapshot of paper or photos through literally switching the variables of the REAL item to the specific snapshot, showing it to the mob, then switching back before you can notice. I thought it was a pretty scuffed method while making it, and it may still be, but sometimes that's just how effects are achieved in code: you tweak things in one way while framing it as another, and that gives the illusion of a particular mechanic. Transporting reagents are another example, what that actually is in-code is having an object remove its own reagent by the specified amount while another adds its own reagent. Soap is actually just a container for Space Cleaner and wetting it with water technically just creates more Cleaner. Another example is with deep space and the overmap: mechanically, nothing actually exists as a z-level outside visitable sectors, so being lost in "deep space" is just a singular temporary space z-level you cycle through until a visitable is reached or dead. Hazards and the like are just things that spawn or despawn when triggered; it feels like you're moving into them, when they're really spawning into you. Changing your perspective to understanding how mechanics are practically done is a big step for structuring code, it lets you know what are passable foundations and when not to worry. Let's try to put some of these skills into practice by considering some beginner PRs that fit the topics you know: DIRECTION 2/4: Example Beginner PRs 1. Inheritance 2. Single Scope 3. Access and Assignment 4. Operators You literally can't operate code without operators, so you NEED to be comfortable with these. They can modify values and modify the code itself, by controlling what can happen and when. Playing with Procs TODO : [DIRECTION] It's All Illusory Example Beginner PRs You're Not Alone The Aurora Style [DEBUGGING] Visual Studio Code Overview: Tabs, Extensions, Breakpoints Common Error Messages [REFERENCE MATERIAL] Aurora's Type Structure Quick Reference ANSWERS QUICKREF HOW TO RUN MULTIPLE BYOND CONNECTIONS FOR TESTING QUICKREF HANDY ADMIN VERBS QUICKREF HOW DO YOU DUPLICATE OBJECTS? QUICKREF WHAT DO THESE ERRORS MEAN? QUICKREF WHAT ARE GLOB, SS, and _ PREFIXES? QUICKREF WHAT ARE /// and /** DMDOC COMMENTS? QUICKREF WHAT ARE STATIC VARS AND VAR_PRIVATE? QUICKREF WHAT ARE BITFLAGS, 0x1, AND 1<<1? QUICKREF WHAT ARE SINGLETONS? QUICKREF WHAT ARE LAZYLISTS? QUICKREF WHY DO THESE PROC DECLARATIONS ALL RETURN? BASE INTERACTIONS AND FEEDBACK QUICKREF COMMON VARS AND LISTS QUICKREF COMMON PROCS AND MACROS QUICKREF OUTPUT OR DISPLAY FEEDBACK QUICKREF INPUTS OR INTERACTION, HYPERLINKS AND TOPICS QUICKREF CHECKING FOR CONDITIONS ADDING TO TYPES QUICKREF HOW TO CHANGE ICONS AND SPRITES QUICKREF HOW TO ADD TURFS AND FLOORING QUICKREF HOW TO ADD OBJS (ITEMS/ORGANS/AUGMENTS/MACHINERY) QUICKREF HOW TO ADD MOBS USING SYSTEMS OR BACKEND STRUCTURES QUICKREF THE OVERMAP & AWAY SITES QUICKREF WIRES FOR HACKING QUICKREF USING POWER QUICKREF ADDING IN RECIPES QUICKREF SURGERY STEPS QUICKREF USING REAGENTS QUICKREF HOW TO ADD TO LOADOUT, WHY CAN'T I SEE XENO LOADOUTS? QUICKREF HOW TO ADD TO CHARACTER SETUP QUICKREF HOW TO ADD TO DATABASE USING SQL QUICKREF SIGNALS QUICKREF COMPONENTS (THE MAIN CODING GUIDE IS FINISHED, YOU CAN READ AND UNDERSTAND EVERYTHING IMPORTANT)
- 1 reply
-
- 2
-
-
Lore Impact (Small/Medium/Large): Medium. Depends on how you define it, but it's Medium to me because it extends lore almost purely additively, there's not a contradiction or retcon, and nothing is missed if you don't immediately read about it. Team Purview: (Vaurca) Short Description: This is to flesh out the post-mortem culture of Vaurca VR. Having an invented, readily-accessible afterlife has huge implications for background context, and I aim to explore those implications. It answers four questions, 1) What happens to Viax consciousnesses when they die? | 2) Is there an introduction process or psychopomp role for how they'll spend death | 3) Phases for non-transubstantiation | 4) Is it taboo for dead Vaurcae use proxies to affect the living? A1) Viax memories and habits are saved as a library for the reference of future Bound. Popular, useful, and dominant libraries are the Viax-equivalent of Xakat'kl'atan status, and it varies per brood. A2) Reconvening is when the dead meet their Hive again in VR, this usually happens in a specific realm where they're processed and choose a domain of 8 to specialize probably forever under A3) 90% = mood swings, 80% = kinda out of sync w/ VR, 70% = gaps in memory about past life, occasionally mismatched reactions, 60% = forget chunks of life & cannot recognize memories of life, 50% = glitches affect vicinity, 10% = memories of life gone & can't recognize A4) Only when it's obvious and distinct such that an outsider would tell and place responsibility on them. How will this be reflected on-station?: Domains are mostly background lore, but can influence the behavior of characters as they have some in mind as goals. Bound libraries will give the rare Viax character distinct habits to roleplay around if desired. Does this addition do anything not achieved by what already exists?: Wouldn't be making this if the answers existed. Do you understand that the project may change over time in ways you may not foresee once it is handed over to the Lore Team? Of course and since this is a lot of lore under one banner, I don't even expect to get 100% of this in. I hope the idea and intent behind each decision is understood and preserved. 1. Bound are included in the afterlife and, just like they're the logistical foundation of physical society, they're the foundation of VR society too. 2. The afterlife is a right, rarely retracted just as mindvoiding is taboo, and also the Vaurcaesian form of higher-education. 3. Non-transubstantiation is gradual and its effects are more inconsistencies and disassociation than losing identity. Must still be preferrable to no afterlife, but worse than not living to transubstantiation. 4. Bound aren't just workers, but extensions of their broods' goals and should passively or actively represent them. 5. Deep-imprinted Bound allowed for more advanced roles like Xenobotany, Xenobiology, Corporate Reporter, or Paramedic (tbh, it's weird they can't be specifically this role in medical already) Long Description: 1. Bound Afterlife with Virtual Reality 1.1 Dominant Libraries of Each Brood. 2. Reconvening and Domains I like to imagine under Vaurca morality, an afterlife without privilege for Queenless is genuinely considered better than none because returning to VR is such an expected stage of their existence that rejecting it for anyone is beyond cruel. Rejecting someone the afterlife is probably like if a human raised a child and then left them without possessions to die in nature. Meanwhile, the Queenless' fate themselves is literally guiding others to a fate they themselves cannot posses. Weavers and Bearers are intentional titles to link to and imply why C'thur and the Viax bioform have those names. By the way, I like the idea of Vaurcae using the term returned instead of departed for the dead, giving way to "newly-returned" and "recently-returned" 3. The Destabilized 4. The Dead's Influence On the Living .
- 1 reply
-
- 2
-
-
I've made a PR that finally splits Pilot: Spacecraft into multiple levels. Rest of this will be copy-pasted from the PR desc: Piloting is now split into three levels like other skills which note what pilot class of vessel you may comfortably pilot. (Familiar) Shuttle Pilot is for all landables: Spark, Canary, Intrepid, the Quark, and the like are all equal under it. (Trained) Class II Pilot covers most ships, which are "overmap-only" and unable to land or dock. (Professional) Class IV Pilot covers only the Horizon normally, but design-wise extends to whatever is the main player ship, or for anything massive Antags get Professional Pilot, so they can always do ship hijack gimmicks without worry. As a convenience to make Bridge personnel stand out, Professional/Class IV Pilots can deduce their current overmap coordinate from examining space on help intent for 3s. There's no way to directly link to the overmap, so on the backend, this ability briefly references an existing helm ship console. Design Class II and IV are pre-existing terms in-lore, used on the Interstellar Travel page to refer to civilian size classes. With how important each level of piloting is, they cost +4 points each go 4 -> 8 -> 10 instead of going 2 -> 4 -> 8. This lets there exist the occasional pilot character from any background, but it's always an investment and piloting the Horizon stays hard without training. As Familiar currently costs 6 points, this is effectively a 2-point buff for most cases as you'll rarely have to pilot non-shuttles. The real meat of this PR... is that you can now attempt to pilot vessels a level higher than you with penalties, so there's now a failure spectrum should you manage to access an adjacent-class ship rather than always being hard-locked. The penalties affect acceleration, slowing, turning, and rolling. They're most extreme for Shuttle and Class IV to represent how clueless an unlicensed pilot would be and how complex the Horizon realistically is to operate. With smart usage of autopilot, you can actually find a way to travel normal-ish. I think this is a fun interaction to have for underskilled characters, and makes autopilot actually have a use as it otherwise kills you. Maybe Bridge personnel can give lessons to Class II pilots with it. Piloting Education Backgrounds (Editing text after spoilers when it's the end is annoying/impossible, so I'll write here): My favorite mechanic added here is the emergency power bypass for ship consoles, I like it so much I want to have it for all consoles in the future. It's the perfect mix of a useful solution for an emergency without overriding the problem.
-
About these new sensors (from an Intrepid main)
GreenBoi replied to Captain Gecko's topic in Archive
This PR tweaked heat efficiency to make it so cooling down sensors is a lot faster, and I think this alone removes about all the clunkiness; the range buff is a cherry on top.. Couple this with Matt's test-merge that adds a roundstart Points of Interest list and I see no issue left besides datalinks breaking when you dock. Having to re-trace contacts that left your view was only awful before because ships had nerfed ranges and heat took so long to cool down that you couldn't reliably stay on higher ranges. Same for more hazards blocking sensors. I'd say now that both of the above enhance the experience now instead of taking away—most obvious in combat, ironically enough. They also keep the buffs from being too strong. Hazards can be used to break contact and retreat, but one can spin them to enable a counter-attack where you spam-accelerate your ship to get closer for more hits while the enemy can only approximate your location with only the periodic tracing updates to go off until contact is fully established. A similar strategy can be tried with shuttles to use them as impromptu boarding pods, or as distractions to bait the enemy to facing the wrong way. Sneakier tactics are possible and I like that a lot. -
This doesn't seem sensible just by virtue of space being much larger, and would make a logical inconsistency with the existing psi-ping: Skrell would be able to sense life from star map grids, but also somehow be unable to sense if there's a person at the other side of the hall?
-
About these new sensors (from an Intrepid main)
GreenBoi replied to Captain Gecko's topic in Archive
To add QoL suggestions to the post: - Datalinks should not be severed when you turn sensors off. This doesn't add anything other than tedium re-linking after docking back. - Contacts shouldn't be forgotten immediately after they leave view. While I have yet to try ship combat under this, I don't doubt having to re-trace ships after they leave view wouldn't slow down gameplay and be very frustrating icly and oocly. Contacts should be 'lost' over time, like how they're first identified over time. -
Hall of Fame Application to Immortalize the Hall of Fame
GreenBoi replied to Lonefly's topic in Hall Of Fame Applications
i'm verbally (textually) giving support because I want my name in history -
I'd say suit sensors are what actually add most of the intrigue. People knowing someone got hurt is what usually escalates a round, and it's less risky than purposefully leaving a corpse in a public-ish area. The victim's health being broadcasted doesn't actually out any info about the antag, so it only adds to the atmosphere. Suit sensors also spawn randomized; most people forget to set them to tracking if they're not Sec or reminded by medical. Most antags (including Traitor) have easy access to stuns, and any notable side-effect comes gradually. Paralysis Pen is just 1tc, Stun Talismans as Cult are just made from paper, and Vampire stuns are literally free. Add that Sec can't use cams on Green, and it's not really hard to get away with stuff without being seen.
-
I think this just removes different avenues for Vamps with nothing gained and just holes left behind. Also confused on how it would even be more fun. The mainstay Vamp combo is: Hypnotize -> Grab -> Feed If feeding would leave the victim conscious...you just have a very straight-forward death each time. If the victim isn't drained to death for whatever reason, they will have enough of their blood drained that it becomes mechanically harder to play (mainly screen-shake and possible collapses). I don't think it's a stretch to say this is worse than just being minorly inconvenienced. Vampire can often be OOCly boring, but I'd rather that than frustrating gameplay or deaths you can't fight to evade. Also, yes, both the above can happen even with memory loss, but there's much less incentive to do so..
-
This doesn't feel that moody, and I feel like it's something you'd just forget about after a few rounds; it's like adjusting your screen brightness. I think we can just use more red lights like maintenance for, well, 'maintenance' or engineering-focused zones. Both the Tesla and SM Engine rooms should be red bulbs and tubes by default imo, to give an appropriate sense of 'Woah, this is something that can easily fuck up and ruin the station!' for the dangerous work engimains do at the start of every round. And for the average crew member, stepping into those red-lit rooms could make them more...cautious. Yellow lights (diluted) could be for a bureaucratic look. Done well, it's not jarring from white, but keeps a weirdly fake-sterile tone. Green can be exclusively for medical wards.
-
Type (e.g. Planet, Faction, System): Vaurcae as a whole, but the K'lax get a lot of focus Short Description: Vaurcae make special boxes for Sedantis nostalgia. How will this be reflected on-station?: Puzzle boxes could be selectable from loadout w/ some mechanical differences. Does this addition do anything not achieved by what already exists?: Puzzle boxes didn't really exist before Do you understand that the project may chansge over time in ways that you may not foresee once it is handed over to the Lore Team? Yes all too well , this is really just a formal suggestion, even when accepted. Long Description: Notes: If the text flows bad, it's because the original draft got deleted from tomfoolery and I had to rewrite everything from memory in three hours.
-
May I suggest borgification, in these trying times?
-
I'll miss 'em...
-
Type (e.g. Planet, Faction, System): Sol and Tau Ceti Describe this proposal in a single sentence (12 word maximum): Movie-going evolves to become more of a social event, rivalling sports. How will this be reflected on-station? It can't really be reflected onstation, but it gives a unique little bit of extra culture so future humans don't feel so similar to present us. Does this faction/etc do anything not achieved by what already exists? It removes the short-sightedness of some written things. Similar to how those in the past thought mechanical horses and auto-driven carriages were the future: we too are shorted by the present. Movies and other subcultures don't have to stay the same and they probably won't. Why should this be given to lore developers rather than remain player created lore? This can't stay a headcanon because it is too massive of scale (for something small) and currently a bit too obscure for anyone to just pick up and get from me casually referencing it IC. Do you understand that if this is submitted, you are signing it away to the lore team, and that it's possible that it will change over time in ways that you may not forsee? Yes, though I would still be slightly annoyed if this was taken....then just dunked on. Long Description: As subscription-based, video on-demand (also known as VODs) services became more popular and profitable- the cinema industry began to fall. No company wanted to die, but none of them could compete with the already giant VODsites people were now using; cinemas could not force things to stay the same and they could not squeeze anymore money from concessions or ticket inflation. The companies needed to adapt and create their own ways of hooking people in and, through an analysis of hype-culture and a retrospective on what made them so much money in the first place, they did. The industry was forced to evolve and keep itself alive, the classic movie theater was now mostly a thing of the past as old theaters were essentially mummified, turned into museums to gawk and be in awe of. Movie Stadiums became the new norm- capitalizing off of hype-culture to feature only the most anticipated films each week, and even readying itself for the inevitable bad film with offers of pausing and rewinding to laugh and mock the production live. The Movie Stadiums of present-day have nearly all been absorbed into the Megacorporate Giants that are Zeng-Hu and NanoTrasen and have been funded greatly, making holo-projections and AR even more common. Zeng-Hu Stadiums are known for their opulent atmosphere, giving even the poorest man with just a few hundred credits the ability to feel premium and fancy; their staff is a mix of low-paid humans and synthetics, with simple drones and Mobility Frames often used to deliver orders while humans man the ticket booths and announcements. NanoTrasen Stadiums are popular for their humor and their casual environment, smelling of grease and cheap food while the stands and booths sell such. The corporation has also used the numerous small-time businesses immediately merged into itself by Tau Ceti Law as "backup staff" at times, it is not unorthodox to occasionally hear music or songs from lesser-known music groups- or for a movie that has turned out to be so horribly bad, have a holo-projected comedian crack jokes as the film is paused; the quirky and jokey nature of some of the stadiums are what keeps people coming back. Notes: I know this is a bit long, but it's honestly the condensed version and it still might be hard to condense onto the wiki. This doesn't feel fully complete in my eyes, and I may add example subsidiaries or stadiums so it can be condensed easier? If that makes sense.
-
He keeps refusing basic ASMR. I gave him a choice on joining back unathi discord or giving me ASMR and he chose NONE.
-
Though personally I'd be fine with being able to combo a bite into a headbutt- I know why it's an issue, especially since you literally can do 50 damage in like 1 second if you have a bite macro. However, if biting just drops the grab- I think that would be fine since the person would probably know to now run to not get bit again and keep distance. The bites have a 7-second cooldown right now, so you can only do the 25 once and then have to rely on your claws to do another 25 (which technically isn't really hard, nor is getting 25 damage WITHOUT the bite which a lot of people forget about)
-
That's because every vaurca species mechanically, except Warforms, are frail. They will never be tanky unless they had some way of clotting and not having to constantly worry and care about something literally no other species cares about. If you get downed or stunned at all, you have to pray your enemy doesn't remove your breath mask so when you get up, it isn't a downwards-spiral of a fight as you suffocate and start blacking out while trying to run or fight.
-
Throatslits easily causes suffocation and can rapidly kill someone from the low BO. Bugbite only does a flat 25 and causes bleeding, but you can do that 25 and bleeding far faster with normal claws, before you get to the killgrab. Force gloves should be taken out of the equation for the most part since they don't come up, and this is assuming people are unarmored and w/o real weapons.
-
So, not too long ago- there was this PR that made it so Vaurca Warriors would now need a strangling grab to bite, and also increased the cooldown from 5 seconds to 7 seconds. When I first saw it, I disliked it because I thought it'd be an overnerf/make the bite useless. I was re-assured and believed the change wouldn't be that drastic, but after a few months of observing and personal experience, I've come to the conclusion that the PR did cripple Warriors too much. Specifically on the part of a person's reason to be threatened by a Za in the first place. If a person was dumb enough to go hand-to-claw against one of these bugs, and actually intend on doing lethal damage- they'd most likely get extreme physical trauma from these bites and learn the hard way to know their match-ups. The reason for this in the past was because you could bugbite with just a bluegrab and that'd be it, you could also combo this into a headbutt if you were looking to seriously mess with the person. Now, it's literally better just to claw at an opponent than to ever use your bugbite. By the time you reach the strangling/neckgrab that lets you do the 25 damage bite, you could've easily have done that damage by simplying clawing. I know this sounds like powergame talk, but this is really just about efficiency and necessity. You have no need to ever use the bite, not even as an execute because of how long it takes to get to it. There's also the fact that you can do a headbutt for 20 damage on bluegrab too (You take 8 damage yourself, but that's 40-16), which is just better. With this in perspective, I think it makes sense why it'd feel like the bite is just crippled beyond usage now. A Za has nothing naturally threatening with their arsenal right now, their very own bite needs them to neckgrab someone- at a point where you could already and would be better off just neckslicing them as an execute. Them being strong in melee is not that bad considering the fact that the most they add to it is their bite, and other species can still headbutt or have their own tricks. Humans...are humans. Tajara can kite, for the most part. Unathi, have the strongest headbutt and can teleport away for a split-second (and so can Skrell). It's not that hard to escape bluegrabs, or run away/kite before they can grab you. Anyone with proper armor won't be as hurt by it since it's just brute, and if the concern is that unarmored people can easily die to it- isn't that the point? It's lethal if you're an idiot or have no armor, as a shotgun slug would be, as a laser rifle would be.
-
Ambrosia is still locked behind the contraband section of the seed vendors because NT doesn't want their employees getting high easily, but I think smokeable joints should be in the ciggie vendor. Make them their own brand, like "Dirty Doobies" or something. Have them have both nicotine and ambrosia so I can icly get addicted to both.
-
Self-made lights are almost always weaker than natural lighting, unless it's a strong powergamer's light beacon. This means they won't heal as fast (or at all since there's a lightvalue that does no healing and is essentially limbo: no healing, no damage from darkness) which lets you hurt them. In most rooms, just having night lighting on screws their healing.
-
Remov dionaea, IPCs and golems from being valid cultists
GreenBoi replied to Scheveningen's topic in Archive
They did, and it was reverted because IPCs couldn't do anything useful because cults need to make runes to work- they didn't even get special abilities like constructs. Honestly imo, IPC cultists should be able to "warp" into a Narsian construct once converted. They will shed their man-made frame and turn into a Juggernaut/Wraith/Artificer when they choose to. -
Remov dionaea, IPCs and golems from being valid cultists
GreenBoi replied to Scheveningen's topic in Archive
I don't agree on this with the golem aspect because you need a Xenobiologist for that or someone who knows it- this is already pretty hard to achieve, especially if you don't have a person with science access. I see golems as a non-issue, they take time to get to and if you don't have a xenobiologist- that could be half an hour wasted on trying to get adamantine slimes for the chance that ghosts maybe want to play golems. Currently no set opinion on dionae.