Content: Slate Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate Marble
Background: Slate Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate Marble
Pattern: Blank Waves Notes Sharp Wood Rockface Leather Honey Vertical Triangles
Welcome to Xbox Chaos: Modding Evolved

Register now to gain access to all of our features. Once registered and logged in, you will be able to contribute to this site by submitting your own content or replying to existing content. You'll be able to customize your profile, receive reputation points as a reward for submitting content, while also communicating with other members via your own private inbox, plus much more! This message will be removed once you have signed in.

Akarias

Members
  • Content count

    477
  • Joined

  • Last visited

Everything posted by Akarias

  1. The game has been updated. Go and get the latest build of assembly from the appveyor. The god damm answer is right in front of you. Perhaps someone should change this to reflect MCC.
  2. General

    "Stealing" maps? thats petty. Yeh, you can goto your recent maps and save them from there so... get over it I guess?
  3. General

    Here: https://github.com/Akarias/Assembly-Compiler Go ham. (MCC only, you'll need to take snipe styles build and fix it up if you want regular big endian support OR fix all the endianess of how the expression values are written. Im lazy.)
  4. Script Expressions: electric boogaloo eiditon If you manage to actually read this and apply it to something give yourself a pat on the back you incredible bastard. Writing this as a blog as it applies to all halo games. PAGE INDEX (Get the pun? you will if you manage to read this all): 1. Expressions 2. Manually navigating expressions 3. Creating a script from scratch 1. Expressions <--- an example of a blank, invalid script expression. Note my plugins are different to the main build of assembly. A quick run down: Expressions are located in the scenario tag of your desired map. Use Ctrl+F to search for things quickly. The Scripts & Globals are also located here. These entries point to a starting expression for the script. Script String Data is also located in the scenario, but its not necessary for normal usage. But if you want any decompiler to be able to read quoted text "sounds\xboxchaos\yeet", you will need to add them to this table and set the String Table Offset in the expression to match this. Again, not required. An expression is x18 (24 Decimal) in length, use this to your advantage for calculating bits and bobs when editing large amounts of expressions as raw hex. A salt is for all intensive purposes just another number that you will need to take into account when writing a datum. (You don't really need to worry about this being unique, just leave any you write as 0. Makes life easier) A index is the position of an expression in the expressions block. (The little number that you see in the top right hand side of a block) A datum is the salt+index. If we think of a datum as a C# we would write it like so: ('Value' being the both the salt and index represented as a unsigned 32 bit integer) Next I will explain the structure of an expression, as you see in the picture above: Salt: one half of the Datum. It's base value will be 58226 + the index of the expression (As per any scripts compiled by Bungie). You can leave it as 0 for anything you write manually. Operation Code: this defines the overall action of the expression, such as the function code to be used when the Expression Type is set as Function. (See the scripting xmls for a list) Return Type: Does this expression return anything to the expression that came before it? This will be void most of the time unless its required. Expression Type: Defines the expression type from a few options, you will be using 'Group' and 'Expression' most of the time. - 'Group' expressions represent a pair of parenthesis '( )' along with any expressions that will be placed inside them '( abc )' & any expressions that will be placed outside '( abc ) def'. 'Expression' expressions represent everything else other than references to other scripts/globals/parameters. You will be using this a good 80% of the time. - Next Expression Datum (Salt & Index): For your convenience you will see the NextExpressionDatum as two separate values. The next expression to be looked at after the current one. (This can be confusing when dealing with Group expressions, explained later) String Table Offset: a simple offset that is created by the script compiler. It stores the original text that was used to create this expression. (The node/atom depending on what you like to call it) Expression Value/Data: this is important and is used any time an opcode/group expression requires extra data. This data can be simple numbers, stringIDs and even a Datum for Group expressions! Line number: do I really have to explain this? Well actually yes. Unless you are using the 'scripting' build of assembly from my GitHub this will always need to have a value of at least 1 or the decompiler does not show it. In Bungie's compiled scripts any expressions with a line number of 0 are implied expressions, this can make navigating a set expressions manually without my build of assembly a huge headache as there will be more expressions than you expect to actually find. This is where people always get confused and give up. Examples of implied expressions are things like 'begin' actually existing at the start of every compiled expression. 2. Manually navigating expressions, following the expression tree by hand Now that you know what an expression is made of, we can finally learn how to follow an expression tree just by staring at them in assembly (or if you are sadistic as hell, in a hex editor). I recommend that you use my 'scripting' build of assembly for the purposes of learning and not having to take implied expressions into account. After you have got the hang of things you will be able to read through implied expressions and realise where they do and don't exist. First find a script to actually follow, I will be using 'objective_3_clear' from citadel in Halo 3. <--- The comment at the top is turned on using the 'Show Extra Information' button inside the options drop down of the Scripts page. <--- If you don't see this, you are not on the 'dev' or 'scripting' build. So let's go to our scenario tag, jump to expressions and goto the index specified by the comment. Alternatively goto the 'Scripts' block in the scenario tag and find your script there. It will have the Datum for your script. You can click on the block inside in the top right and type the number to instantly jump straight to it just like you can in windows explorer with file names. Very useful for maps with 40,000+ expresions... Yikes. So let's take a look at the first expression and decipher what it does... I'm fucking lost? The Next Expression index is 65535? What? Hol' up fam. Dont wet your panties just yet. This is a group expression. Remember that a group has both expressions on the inside and potentially on the outside. <--- 65535 / xFFFF , simple means nothing. Meaning there is nothing outside of this group. This is true, look at your script. Let's ignore anything other than the expressions in our script, the other pair of parenthesis is not actually an expression. <--- What we are interested in. So yeah, having xFFFF on the Next Expression Index is correct but where is the over index for the 'begin' function expression? Its in the expression value! see where we have 4 8bit integers? Between x10 and x13? That's our Datum and where the next expression to be placed inside the parenthesis is located. But we only see -61, 35, 95 & -81. Those make no sense? Well they are actually correct, but due to our plugins we are reading them the wrong way. Think back to what a Datum actually is: Salt+Index and both are unsigned 16bit integers. We can right click on the first int8 at x10 and click 'view value as...' to read from that offset as something else without having to edit our plugins. So let's do that now. <--- just like so, scroll down to the unsigned 16bit values... it reads two of them one after another, very useful for us! So we can see that at x10 there is a uint16 with a value of 49955. That's the salt of the datum! You should be able to guess the second one at x12, that's our index that we need to go to in the expressions block. Here is a visual example in terms of indexes as to what we just read: ( 24495 ) 65535, So that's a group with an expression inside it that is located at 24495 and there is no expressions to be placed outside thanks to 65535 (xFFFF) meaning there are no more expressions to be used outside of this group. Neat. I hope you are still with me on this and not lost. A general rule of thumb for Bungie compiled scripts is that the contents of a group are always placed directly after the group expression, with anything outside that group then coming after the expressions that were inside the group. With this logic now in your head it should be obvious what comes next at 24495, a function with the opcode for begin. Just so happens the opcode for begin is 0. We are actually heading UP the index rather than down, this adds to the confusion. Let's take a look... <--- Yup, Expression with function_name and an opcode of 0. Yeetie. Okay, this is straight forward. Let's follow the Next Expression Index. We will find another group expression at this index. <--- We started at 1, then went to 2 and now we are at 3 as per the next expression index of 2. Here is what we find at 24485, the third expression of our script. <--- we have both a Next Expression index and a Datum in the value. Meaning there is expressions inside and outside the parenthesis. So this where things can be really confusing, where do you find the print expression? At the Next Expression Index or at the datum that is in the expression value? Where is the next line specified? The next line in this case is specified by the Next Expression Index, this means we have a group expression that looks at another group expression and so fourth. This is how we navigate lines. Every new line has a group expression. <--- Well because we want the expression INSIDE the parenthesis we follow the datum in the expression value, so view value as like we did before. <--- we can see that the print expression is at 24486, let's go to it.... <--- here we are, a function with the opcode of 27. Print. Before we go any further, we need to talk about functions. Most functions require an argument of some kind to actually be useful. If we take a look at our script xml file we can see that print requires and argument to work correctly. <--- While print is nulled in the release version of the game, this is not relevant for our discussion right now. We can see the required argument is a string, so with this in mind we know that the next expression after our print function is going to be something string related. Let's take a look now by going to 24487. <--- Take note of the return type and opcode, both are set to string hopefully for obvious reasons. Note the Next Expression Index is now 65535 (xFFFF) and this means there are no more expressions. This is the end of the contents for the group expression as a result and thus the end of this line. For strings the BlamScript engine will read the expression value section for a string table offset. Now when this script was compiled it placed the string for it at 42597. So if we read the value as a Uint32 we should see the same. <--- indeed we see the same string offset in the value section So you by now have likely caught on to the fact that the value section of an expression can really be anything as required and its meaning will change depending on the context. For example an AI expression can actually specify individual AI Units, Groups etc all using the same expression & just the values change to tell the script engine what to look for. SnipeStyle/AMD(?) did a lot of research on this many years ago for Halo Reach and deserves a mention for this. So the line is finished. Let's recap where we are in the index as we are going to go BACK to our line's group expression so we can find the next line. Savvy people will already know where to find the next group expression, but otherwise keep reading. <--- back at 3, we read the NEI for the next line So we navigate to 24488 like so and are greeted by another group expression as expected. <--- we are now at the second print line <--- considering that we just manually read the same expressions, we are actually going to skip reading this line. We know what it is. <--- Let's look at the next line of the script by following the group expression 6's NEI. It will be yet another group at 24491. <--- LAST LINE OF THE SCRIPT YO. So this is the last line of the script, we can tell this because the group for this line has its NEI set to 65535 (xFFFF). The BlamScript engine will see this as the script being finished, but let's continue by investigating the contents of this group. Thus we must do our typical 'view value as...' or if you are savvy you will know that it is on the follow index. Let's take a look now. <--- a function with opcode 1100, objectives_finish_up_to. It requires a long (32bit integer) to work correctly. So this function requires a long to work correctly, so with this knowledge the next expression specified by the NEI should be a long. Let's take a look... <--- Piece of cake, if we read the value as a Int32 from x10 we get 2. Lovely. never take what your plugins say for face value. <---So that's it. We can see 2 down there just like we see in our script! Done. That's the end of the script! Feel free to add extra lines to your plugins for making ready Values easier, such as adding two uint16 readers at x10 and x12 for Group Salt & Indexes. I leave it to you to decided how you want to go about this. Personally I use a hex editor with a data inspector and calculator as it's just faster for me. So that's pretty much it for reading scripts by hand, as long as you follow the rules of how group expressions work you will be perfectly fine. Have a go at navigating a complex looking script and changing numbers. This is good practice you. Enjoy reading nested expressions, it's a hell scape. Thanks LISP. <--- You should be able to mentally know where the group expressions are, have a think about it because you will be writing this manually soon. <--- This makes me hard just thinking about it. oof. 3. Making a script from scratch So now that you can read scripts its about time you started writing them, that's what you came for right? Well bad news buddy if you just skipped everything that I wrote there you are a total jerk. Go read it. I wont answer any questions that you ask if you are not able to prove you can read expressions yourself, otherwise whats the point? If you cant read them you cannot understand how to write them. I'm going to assume you are using a map with no scripts or you have removed all the existing scripts. I leave the allocation of Datum Indexes to your own discretion. I'm going to use Valhalla in Halo 3 as it has no scripts by default. Start by adding a block to the scripts block in the scenario tag. Give it a name and set the script type to Startup and the Return Type as void. We are not returning anything and this is normally used for more advanced scripts, such as a script that continuously returns a list of all objects that are inside a trigger volume to be used by another script. You can make some pretty advanced stuff. But for now we are sticking to the basics and doing a basic script that toggles the gravity between high and low every few seconds. We will do this using the physics_set_gravity opcode and the sleep opcode. So let's review the script before we begin: <--- We will set the gravity to 30%, wait 3 seconds, set the gravity to 130% for a nice slam dunk and then wait 3 seconds. The script will be set to continuous so it will repeat after it ends. Your mind should already be racing, you already see exactly how many expressions you need and what they need to be set too. 14 Total. (Or I'm just really fucking weird because I can. I hope you can too.) I will number them out below: Group, NEI: Datum(65535,65535), Value: Datum(0,2) Function Begin, NEI: Datum(0,3) Group, NEI: Datum(0,6), Value: Datum(0,4) Function physics_set_gravity, NEI: Datum(0,5) Function Real, NEI: Datum(65535,65535), Value: Real(Float) @ 0.3 Group, NEI: Datum(0,9), Value: Datum(0,7) Function sleep, NEI: Datum(0,8) Function Short, NEI: Datum(65535,65535), Value: Short @ 90 Group, NEI: Datum(0,12), Value: Datum(0,10) Function physics_set_gravity, NEI: Datum(0,11) Function Real, NEI: Datum(65535,65535), Value: Real(Float) @ 1.3 Group, NEI: Datum(65535,65535), Value: Datum(0,13) Function sleep, NEI: Datum(0,14) Function Short, NEI: Datum(65535,65535), Value: Short @ 90 Note that '12.' is the last group expressions and as a result has a NEI of 65535 (xFFFF) effectively ending the script. Now I would write out an even longer section of this blog but instead I will show you a video of the process. [NOT DONE YET COME BACK LATER FAM]
  5. .MAP

    The additional AI will be seated in the pelican (if not, you will have to load them in manually with a script), but they wont get out unless you modify the relevant seat mapping to also have w/e seats included. (Woo my fancy node editor, should help you visualize it)
  6. .MAP

    The pelican's squad in the scenario tag has a command script set. Every time the squad is created, it will run said script. <--- Single Location Block You can just run call ai_place, but if you want more marines inside of it, you will need to add more of them on the pelican squad as passengers and adjust the seat mapping so they all exit correctly.
  7. Something else I was fiddling around with, hoping it will help people get their head around things. Feeling a bit rough, nothing a bit of halo stuff cant fix. Originally started this as a means to an end for learning MVC after encountering it in node network. UIs are not my forte. Edit: Finished writing the solver, needs more work for memory and initial placement plus alignment.
  8. Modding

    Sound injection is not automated. *
  9. Modding

    Continuous scripts + checking VERY large volumes will do that.
  10. Modding

    Its all down to missing animations. A nasty but fast way of dealing with it is to reuse existing animations with a new stringID to match that of the phantom_p etc strings.
  11. A thing I've wanted to do for a while. My custom nodes are not being displayed due to an error but you get the idea.
  12. Loop through your list for the amount that exists in the list, `list_count` will give your max count while `list_get` will return each object in that list. `volume_return_objects_by_type` is handy for filtering things out, so you wont be trying to pass unwanted engine objects that a volume check would get. Would be a good idea to make sure the AI you end up casting is actually alive too. Edit: You may want to take a look at how AI expressions are used, take a look at some campaign examples. They can be setup to reference a bunch of things including whole squads, objectives and tasks. Situational.
  13. Looks at the string name as defined in the Collision Region block. That block then defines the index and various permutations if there are different damage states. Its doable.
  14. (H2X) ScriptTools Beta

    Version Unknown

    18 downloads

    A script compiler/decompiler created by Soldier of Light some years ago. Original readme is below:
  15. Modding

    Those are just biped units. They wont have any AI associated with them. The units need to be crated via character tags.
  16. Woo reach is on PC now! Time to mod the living hell out of it. Before we get started, make sure to make a backup of your game files, for steam users you will find them under: 'C:\Program Files (x86)\Steam\steamapps\common\Halo The Master Chief Collection\haloreach\maps' Assembly: https://www.nexusmods.com/halothemasterchiefcollection/mods/1 Only download assembly precompiled from the above link Modding MCC is actually rather straight forward if we are just talking about map files, its business as usual if you have experience modding previous titles both on console and PC; Simply navigate to the map file in assembly and open it up. You can poke, save & of course extract and inject tags between maps! If you are looking for tutorials there are plenty of them here on the websites, I will admit most of them are quite old now but their ideas still apply and there is much to be learnt from reading them. Check out the various tutorial sections. One thing to remember is that the Halo games are very similar when it comes to their tag systems, most methods / ideas can be applied to multiple games so dont be afraid to explore and adapt old information that you find kicking around. I've never modded halo before, what should I do? Experiment of course! Each of the levels that you play in game are stored in .map files. You can use a program like assembly to open these files and tinker around with its inner workings. When you open a map you will be greeted by a screen that looks like this: Looks pretty scary right? Wrong! Welcome to tag modding! Every single thing that you see in game has something called a "tag", on the left hand side of the screen you will see the various "classes" of tags that comprise the map. Take a look at the [bipd]Biped class, its where all the various bipeds that are used for players and AI etc are stored. If you have a campaign map open, you can open the spartans biped tag to see some infomation. For multiplayer open the spartans_mp biped tag, or if you are playing as an elite... I think you get the idea. Now take a look at the new screen that has opened up, we call this the meta editor. To make a long story very short its just a very fancy looking hex editor that makes your life easy when it comes to finding and editing tags. You can scroll down using the scroll bar on the side, but far more efficient to search for what you are looking for. Press Ctrl+F to open up the search bar and you can then type in the name of what you are looking for. Lets look for "jump": You can click on the drop down box to choose from the various found items, it will take you straight to them. Neato. We can see the jump velocity and that it is stored in the tag as a single-precision floating-point value. Let's do something silly like change it to 5. You can then press save and start the map in MCC... or if you already have the game running and open on that exact map you can do something called "poking"; poking lets you make changes in real time so there is no need to save and reload the map. (Please note that having a map open in MCC means you will not be able to save to it, so return back to the lobby before you save any changes.) Poked changes only exist while the map is running. After you end the game the changes are lost. Note: poking can cause crashes but it depends. That's it! Your first ever MCC mod done. Why not explore the [weap]weapons tag class and see what you can cook up? Perhaps some vehicles? There is too much to cover in a single post so carefully explore around the various tags, see what interests you and play around for a while. When you feel ready take a look at some of the tutorials that are kicking around and have a go at them, build your knowledge and it will be second nature to you. You wont be creating AI, forging in campaign or doing complex things just yet. Learn how the system works first. (Feel free to download patches for these though, nothing wrong with that) I hope this helped you out if you are new around here or to modding in general. Not many people have stuck around to mod reach over the years but perhaps that will change now. Go make some cool stuff! You can also refer to zedd's older posts, ignore anything console related. I dont feel like rewriting it all.
  17. General

    Its much easier to do on ReachMCC. Just inject the various globals and add some entrys to the sandbox pallet. Go ham.
  18. Modding

    No they are they can actually be accessed in retail builds with a button combination. Haven't tried it in MCC though.
  19. Sound injection is not finished yet, you can still inject them manually if you are really desperate. I dont have the thread on hand but someone wrote a guide for it on here a few years ago iirc.
  20. Modding

    I've just been using my previously ripped BSPs from the console maps in 3DS.
  21. General

    Well an entry radius of 0 wont work. Well... anything? Snipping Tool? ShareX? WindowsKey+Print Screen? https://getsharex.com/
  22. General

    Could you show us a screenshot of what you have setup? Have you set the entry radius and cone angles?
  23. Reach has two scripting systems, one of them is the map scripting system that is used for campaign and firefight. There is no public script compiler that is feature complete, snipe style has been working on some bits but I haven't taken the time to see what hes actually been working on. I haven't checked to see if scripting synchronizes in multiplayer so it may not be of any real use as the states of scripts wouldn't be synced between clients, things fall out of sync and it all goes to hell. Scripts are ran in multiplayer but are relegated to triggering garbage cleanup. The other is called megalo. This is used in gametypes in multiplayer and is actually quite powerful but you wont be able to achieve what you describe with megalo alone. I'm not too familiar with it as it does not interest me, see some of the megalo threads and tutorials.
  24. The quick and dirty way to load directly into other zonesets. USE SCRIPTS YA FUCKIN' DEGENERATES REEE Useful for campaign to multiplayer conversions. Unless its for multiplayer, thats fine. Those with experience can meld together multiple zonesets/bsp related data to load more BSPs. IF you understand how zonesets work of course. 1. Find your desired zoneset. Traditionally you would see the blue text pop up in the activity feed on the lower left of the screen saying "Loading... Done.", this means a zoneset change has taken place and new assets and BSPs have been loaded into the simulation along with unneeded assets and BSPs being unloaded. This all existed because of memory constraints on the xbox, duh. These are normally triggered by... triggers... You can find the settings for these triggers under the "Zone Set Triggers" block in your scenario tag. If you haven't it out: zonesets define what BSPs are loaded or unloaded at any given time. So work out what zoneset you want to load. I know pretty much all the zonesets, tends to happen after plenty of years staring at them. You can always look at what BSPs are loaded in the zoneset from the "Loaded BSPs 1/2" bitfields and reference them as indexes to the structure BSPs block. If you own the xbox 360 version you can use adjutant to load the BSPs etc. <-- I'll be loading set_facility on m35. 2. Modify the Scenario Zoneset Groups block Now that you have decided on a zoneset to load, goto its index and rick click on the plugin entry for "name" & click "View value as...". A new window will open, copy the memory address. Click on the little 'i' at the end of the block, this will open additional information on the block and allow us to overwrite the block address. <-- Copy the "Memory Address" and paste it into the "Address", set the "Count" 1 and press enter. Save changes. 3. Disabling scripts (optional, but recommended) If you load your map file now some weird things may happen, you will either spawn outside of the loaded BSPs thus not actually spawning at all or you will have scripts attempting to run causing all sorts of issues depending on the map and what your insertion point is set to. (Insertion points trigger the loading of different zonesets, as defined in the mission startup script). I recommend you disable any scripts from running unless you have the ability to modify them and resolve any issues that pop up as a result of doing some screwy things that the scripts will not be expecting. Goto the script decompiler, enable "Show extra information" option from the options menu on the bottom left, press Ctrl+F and search for the word "startup". Move through the results until you find the main missions startup script. <-- You will know it when you see it. Typically it will have the mission name in the script name. Make note of the "Index: x" number and go back to your scenario tag. Goto the scripts block and navigate to the index you just noted down. You can click on the index and then type the number to jump directly to it. When you are at the startup script index set its " Script Type" to static. <-- Startup scripts are now disabled. The mission wont load any AI or cut scenes etc. 4. Moving/creating player spawns For single player and co-op you can use the "Player Starting Locations" block to set the spawn locations for players, some maps will already have these present for your zoneset (Such as in Halo 3), if not you will need to find a place within the loaded BSPs to spawn the players. If you are doing this for multiplayer & or forge you will need to use a spawn point object instead, extract a scenery tag like "respawn_point_invisible.scenery" and place it via the Scenery block in your scenario tag. Again, you can use something like Adjutant to get the XYZ coordinates or if you have dumped the BSP you can use 3DSMax by setting your "Unit Setup" to 100 inches. See below for specifics on that. <-- adjust these values to reflect a location within the loaded BSPs. Well that is it. Load the map up and you will now spawn in your desired zoneset. More work will need to be done if you wish to convert the campaign map into a functioning multiplayer map, specifically you will need to fixup the various globals. Those familiar with scripting can alter the existing scripts to trigger and work correctly, even with the forced zoneset. if you know how to do that then why the hell are you not using the switch_zone_set opcode, jesus.
  25. Support

    Please check the date of threads before you reply to them. Depending on where you are in the level, the asset may not be loaded. If you dont fancy loading the assets correctly you can force them to be added to the global zoneset. Right click on the tag, so in your case the projectile tag and click forceload. It should now work regardless of where you are in the level. Be warned that loading too much can cause problems.