• Register
Post tutorial Report RSS Guns and Rookies: An Introductory Guide to Basic CC Gunnery

This guide is meant for the very beginners of Cortex Command modding, currently up to date as of November 2022, C4V2.

Posted by on - Basic Client Side Coding

Guns and Rookies

An Introductory Guide to Basic CC Gunnery


This guide is meant for the very beginners of Cortex Command modding, currently up to date as of November 2022, C4V2.
By the time you finish this guide you will have access to enough info to make anything from tiny semi-automatic peashooters, to automatic shotguns and flak cannons. This includes knowing:

  • The very basics of .ini structure
  • The very basic hierarchy of bullet-round-magazine-gun
  • The properties of a bullet - sharpness, mass, etc.
  • The properties of a round - firevelocity, particlecount, separation etc.
  • The properties of a magazine - tracerrounds vs normal rounds, etc.
  • The properties of a gun from the obvious to the less (particlespreadrange, etc.)

Important: Everything below will be much easier to understand if you download the following mod, since it only contains important bits so you don't have to scrounge through vanilla content or other mods. I will also refer to it throughout. Credit to idiot bean for the content within.

Simple Gun Mod

Basic .rte

an ".rte" is a folder of any name with .rte on the end of it. This is a normal folder, the ".rte" is simply part of the name. The .rte on the end of the folder tells Cortex Command to load it. Any mod .rte must sit together with other .rtes. If you want to quickly disable a mod from loading, you can take away the ".rte".

Cortex Command, inside an .rte, looks for one file only, initially: "Index.ini". This is a normal text file, but with the filetype .ini. You will have to "save as" in your preferred text editor to avoid saving as a .txt. Notepad++ is a good text editor - you should avoid basic notepad. The Index.ini is the starting point of your mod structure.

Any .ini can point to another .ini via an "IncludeFile" line. Once the game reads this line, in this case in Index.ini, it will immediately go to the pathed .ini and read it to completion before returning. However, there's an accepted standard of when to do this.

.inis usually fall under structural .inis that only point to other .inis, and content .inis which include actual definitions. Index.ini is special because it both defines your mod - your "tech" - and points to other files. Actors.ini, Devices.ini are examples of "structural" .inis. Brno.ini, Soldier.ini are examples of "content" .inis. (Actors/Soldier not in guide)

Basic .ini

Before we can think about guns, we need to figure out how any .ini of any sort works.

CC's .ini system is extremely simple. It is a tab-based hierarchy of definitions, that is to say you will start by defining an object like a Round, and its properties will be tabbed once "under" it to tell the game that it's a property of that new Round.

A "tab" is literally a tab - try pressing it and you will see one big space show up. A common mistake is to confuse a tab with many small spaces.

The first, untabbed line tells the game a new Round is being defined. Since the following lines are properties of this, we tab them at least once.

Presetname: All things need a PresetName. This is the name of your definition, which can be used in other .ini files, later in the same .ini file, or in .lua files. Once this .ini file is read, the definition is put into memory and can be used by anything, anytime. However, it does have to be read first:

This is how CC loads data: first is Base.rte, then all vanilla ones in alphabetical order, and then finally all mod .rtes in alphabetical order. If your mod is aaamod.rte but you are trying to use a definition from zzzmod.rte, you will fail to load. However, if you use Imperatus.rte, you will be fine.

The internal structure of your .rte matters too. First is always Index.rte, but the order within decides the rest. If you IncludeFile Gun1.ini and after that Gun2.ini, you cannot load something from Gun2.ini inside of Gun1.ini.

Finally, CC reads files top down, so define something before you use it within the same .ini file (for example, define your bullet before trying to CopyOf it into a round).

Particle = MOPixel: Since this is a round, it needs a particle - a "bullet". This will be explained in detail later, but important to note is that this is technically starting a new definition. In this case it's actually a wholly new definition inside of the round, but either way it means the bullet's properties have to be tabbed again to tell the game they're not properties of the round but rather the bullet.

Oftentimes, this is one property: CopyOf, which tells the game to just look at an existing definition and all of its properties. This can theoretically be a new definition - you can CopyOf something then give it a new PresetName, and the game will treat it as an entirely new thing. It will still treat it as a new thing if you give it new properties other than a name, but without a name you will not be able to re-use it later if you want to.

Once this particular property of the Round is done being defined, we go back to one tab so the game knows we're defining the Round's properties again rather than its Particle.

So... what are the properties of things? The unsatisfying answer is that properties vary from thing to thing. You will see many properties shared, but the truth is that everything is, ultimately, unique. In this guide we will only go through the properties of everything required to make a (relatively simple) gun work. The best way to learn what properties things have is to go out there and study them.

Bullets

The quintessential bullet is simply a colored pixel, an MOPixel, flying through the air. The "line" effect is actually caused by a trail drawn behind - the actual bullet is the leading pixel. These two can be of differing colors.

MOPixel stands for Movable Object Pixel. When you kick up terrain by, say, shooting it, this is what comes out of it.

Other things guns use a lot of are MOSRotatings, which are Movable Object Sprite Rotating. The gun is one, the magazine is one, the guy you shoot with a gun is one. MOSRotatings are sort of a "base" class of things. An AHuman (like a coalition light) is an AHuman, but it's also a MOSRotating. A HDFirearm is a HDFirearm, but it is also a MOSRotating.

Something you'll come across often are AEmitters, which are practically MOSRotatings with the ability to emit things (anything!) with many different settings. Rockets are often AEmitters - they literally physically propel themselves by emitting things backwards. Dropship engines as well. Most often, however, AEmitters are used to emit FX that do not propel them, like smoke. You can see this in the uber-cannon's projectile for instance.

Often, including in most if not all vanilla guns, the bullet will be an MOPixel defined inside a Round as it's, often, not important enough to warrant being totally separate.

A bullet like this is a very simple thing, and also the core of many, many CC guns. It has the ability to punch holes in terrain it hits as well as wound actors and cause HP damage among other effects. Every singular bullet MOPixel can only wound once.

The Mass, Sharpness, and the velocity it is going at (defined later and also by its travel) decide how penetrative it is. When it is hitting an MO like an armorplate, an actor's head, or a dropship's engine, this is simply checked once - either you can hurt it, or you will bounce off. Cranking these values up to the max will not make the bullet more damaging, it will simply ensure it never bounces off.

However, penetrative power matters a lot more for terrain. One common issue is putting values very high (as has been done here for example) which will not do anything for the core gameplay, but instead cause ugly holes to appear in the terrain.

Lifetime is in MS. Once this bullet's age in MS goes above this, it simply disappears.

HitsMOs tells the game that this can hit moving objects like people, guns, dropships, etc. We want our bullet to do that, so it's at 1 for yes/true.

GetsHitByMOs tells the game that it can be hit by things that hit MOs. We don't want our bullet shot out of the air (nor do I think that's possible…) so this is at 0 for no/false.

AirResistance only applies if the velocity of this is above the AirThreshold. The inner workings of airresistance are enigmatic but values like this work fine enough, so feel free not to touch em too hard.

Color is a property with its own properties, so note the tabs. This decides the pixel's color in RGB.

Atom = Atom is sort of a courtesy to the game to tell it that we are now defining the pixel's actual physical properties - everything in CC is made out of pixels (atoms) and of course our actual singular pixel is one actual singular atom too.

Material matters if you're getting shot at, but for a bullet it's not actually very important. It decides mainly what terrain a bullet will settle into once it stops moving. For example, a concrete sprayer just fires lots of slow bullets that have a material that settle into concrete.

TrailColor is the RGB of the trail behind the pixels, and the TrailLength is the length of that trail in pixels. You can have this at 0 for no trail at all, which would make for a very hard to spot bullet.

So… where's my shotgun bullet?

You're looking at it. We have defined a single pixel - what we do with it and how decides what kind of gun we are making. The next step is the Round this bullet fits into - or potentially, many bullets fit into…

Rounds

You can imagine a Round as an actual, real life round, with its own characteristics like casings and the gunpowder load separate from the Bullet or bullets that reside within.

ParticleCount is a very important statistic. This decides the power of your gun very heavily. A sniper may have something like 7, which means it will fire 7 pixels at once (only using one Round). A shotgun can have 10, but the gun's properties will cause them to spread like shotgun pellets.

Shell can be any MO (movable object) in the game. In our case, it's a Base.rte MOSParticle (Movable Object Sprite Particle) called Casing, which is a basic casing. Where exactly on the gun this spawns is defined by the gun itself. You can get creative with this - some old mods have used this to spawn smoke at the barrel of the gun. I would not suggest this today.

A MOSParticle is unique because it looks like a sprite, but in truth acts as a MOPixel. It cannot rotate - if you look up the basic Casing, you will see it's actually animated to look like it rotates.

FireVelocity is exactly what it sounds like, and will decide with what speed your pixel(s) comes out of the gun with.

ShellVelocity is, too, what it sounds like, and decides with what speed the shells come out of your gun. Note that using this and the fact that a Shell can be anything, you could do some pretty dumb stuff.

Separation is a confusing one - many mistake it for the property that gives a shotgun-like spread. What Separation does is decide the horizontal separation between the Particles of a round. It will do nothing if you only have one.

Four particles with a high separation value.

Four particles with high separation value.


Four particles with no separation value.


Four particles with no separation value.


This can be used to make a sniper feel more powerful, since this will space the several impacts of one round.

AIBlastRadius is the distance, in pixels, lower than which the AI will decide not to shoot at valid targets. This is typically used with shells that explode to prevent AI-controlled actors from shooting at enemies at too close a range to be safe.

AIFireVel is what an AI-controlled actor believes the round's FireVelocity to be. This property is useful in case your FireVelocity is being modified by lua or aemitters, causing AI to operate the weapon incorrectly. AILifeTime is the same, but for LifeTime.

Loudness defines the range at which AI is alerted by the round being fired, with 0 being completely silent and 1 being the hardcoded limit for loudness.

Magazines

This is your first taste of a MOSRotating style object, with all the overhead that brings.

CollidesWithTerrainWhenAttached decides whether this magazine will… well, collide with terrain while on the gun. If this is 0, the magazine will have no collision while attached to the gun.

Regarding sprites and frames and offsets, there are many guides out there that go in depth into this sort of stuff. Here is one on youtube by trulyapawn, here is one by Envy. and here is another on Github.

JointStrength and JointStiffness are irrelevant, as magazines can never be shot off their gun, nor should they really be shot at all.

DrawAfterParent decides whether the sprite/image of the magazine will be over or behind your gun. For most normal guns, this should be behind, so 0.

RoundCount is how many rounds you'll get per magazine after a reload. CC has no "one-in-the-chamber" system, so unless you specifically alter this with lua this is what you get. -1 means infinite here.

This particular Round is simple and has no Tracer, so let's look at one that does.

RTTRatio denotes how many RegularRounds you get before the next round is a Tracer. You can use this literally, as in a Tracer just being a brighter version of the same round, or you can get creative. In vanilla, most tracers are slightly more powerful than the regular rounds.

The Mighty Guns

This is where all the magic happens - the bullet in the round in the magazine in the gun, which finally decides how to actually fire it. Again, there's a lot of basic MO overhead here, like entry wounds and atomgroups. Here I will be going only through gun-specific properties, or those relevant to the art of gunnery.

GoldValue is a fine trap to fall into as a balancing method. This is how much the gun costs to buy, obviously, and should never truly be above 200 (or below 15). If it is, check if you can't balance the gun some other way.

JointStrength and JointStiffness now play a true role. JointStrength is how much impulse this gun needs to take to be pushed right out of your hands - most basic bullets like the one we just made won't reach 100, but a super-fast gib flying into your gun might. JointStiffness decides how much of this impulse is later transferred to the gun holder's arm, which is later transferred to the body. If this is above 0, this means your gun getting shot could, in extreme circumstances, cause your body to explode.

OneHanded does not decide whether you can dual wield this with other guns, rather it decides if you can dual wield other guns with it. DualWieldable is the opposite, which is to say it decides whether this gun can be held in the offhand or not. In our case, we have a pistol, so we'd like both so that we can dual wield it with other things or itself.

The various offsets you should have learned how to set using the previously mentioned offset guides.

JointOffset is where the ForeGround (FG), dominant hand will be on the gun, and if you are familiar with JointOffsets in general you will know that this is also the "joint" upon which the gun rotates (also respecting the below stanceoffsets, obviously). If you have a rifle, this would be on the grip with the trigger next to it.

StanceOffset is where the gun's SpriteOffset will be in relation to the holder's torso's SpriteOffset while not aiming. SharpStanceOffset is the same but while aiming - this is what achieves that effect of "looking down the sights" when you aim with various vanilla guns.

SupportOffset is where the BackGround (BG), non-dominant hand will be on the gun. Note that you CAN set this too far to reach, in which case you will just be holding your gun with one hand. If you have a rifle, this would be on the foregrip.

SharpLength is how many pixels you can "aim out" with this gun. 100 is on the relatively low end which is good for a pistol. A sniper may see as high as 500.

Magazine tells the gun what magazine it uses. In our case, we defined it before, so now we just CopyOf it. If you're insane, you can define a magazine in the gun, a round in the magazine, and a bullet in the round. This is not advisable, but you can do it.

Flash is what you may think it is - the flash that comes out of the gun's fun end when you fire it. The base game comes with a few, like Muzzle Flash Pistol, Muzzle Flash Shotgun, Muzzle Flash SMG.

The four sounds, Fire, Empty, ReloadStart and ReloadEndSound are the only ones that a gun uses by default. It's important to note that you can add many variations by simply repeating AddSound under the appropriate SoundContainer.

This is the heart of your gun.

RateOfFire is in Rounds Per Minute.

ReloadTime is the reload time in MS, from the moment you start reloading to the moment you can fire again.

FullAuto decides whether the gun is fully automatic or semi-automatic. 0 is semi-automatic, 1 is fully-automatic. Keep in mind that a semi-automatic gun can fire as fast as an identical fully-automatic gun, the only limiter is your clicking speed.

FireIgnoresThis tells whatever the gun fires to ignore the gun and its holder, which can fix issues you may have where the gun shoots itself.

ShakeRange is a value that applies itself as raw spread to where your Round goes - think bad RPG mechanics. SharpShakeRange is the same, but for when you're aiming with the gun.

NoSupportFactor is a multiplier added to the two shakeranges if you are currently holding the gun with only one hand. This is to make one-armed actors and dual wielding worse (or better?)

ParticleSpreadRange is the magic number if you want to make a shotgun - this decides the actual spread of the Round's particle load, so after shakerange is calculated you can then take all bullets you are firing out and fire them in a cone - like a shotgun. In our case, a pistol is not a shotgun, so we have it at 0, but note that this does not at all nullify the ShakeRanges.

A shotgun with a very high ParticleSpreadRange would look like this.

A shotgun with a very high ParticleSpreadRange would look like this.

A shotgun with high ParticleSpreadRange AND high ShakeRanges would look like this.

A shotgun with high ParticleSpreadRange AND high ShakeRanges would look like this.

ShellSpreadRange is a small modifier to how your shell flies out of your gun and the corresponding ShellAngVelRange is one to its angular velocity, that is how fast it rotates.

MuzzleOffset acts best when it is just outside your gun's barrel, NOT just inside it.

EjectionOffset is where your shells come out of, not the angle. Instead, the property ShellEjectAngle is what dictates the angle at which shells are ejected relative to your gun's rotation. This is set to 150 by default.

RecoilTransmission is a multiplier applied to the recoil force of the gun, which is otherwise dependant on how massive and fast the projectile coming out of it is.

Chambering

Chambering is a new stage for reloading, performed after inserting a new magazine and before firing. It is optional and defaults to off.

Chamberable dictates whether the gun is to be chambered or not. Setting this to 0 disables the chambering stage of reloading.

ChamberingStartSound is played on chamber starts. If this overlaps with ReloadEndSound, incorporate a small delay at the start of this sound. ChamberingEndSound is instead played on chamber end.

ChamberTime is the time taken, in milliseconds, to chamber. Similar to ReloadTime.

OnlyChamberOnEmpty dictates whether the gun should only chamber when the magazine is depleted.

So… where's my flak cannon?

If you are clever, you may have noticed that the flak cannons in the game, or many other guns really, don't fire singular pixels. This is because a gun can fire anything. Yes, anything. Even other guns. What comes out of a gun is what comes out of a Round and a Round does not discriminate.

At its core, the quintessential "impact grenade" of a flak cannon is just an MOSRotating with an exploding GibSound and many gibs that can hurt as they come out - like grenade fragments. This is your invitation to get creative - look at explosive weapons and see what their bullet-round-magazine-gun hierarchy looks like.

You'll be surprised to find most of the difference, if not all of it, is just in the "bullet" part. The feared Coalition autocannon is a few sounds and one bullet away from being a really weird assault rifle, and your really weird assault rifle is just a few sounds and one MOSRotating "bullet" away from being a flak cannon.

An MOPixel cannot gib, that is, "explode", so you will need to instead feed your round a MOSRotating that can and does gib into harmful grenade fragments. An AEmitter is simply a MOSRotating that is constantly emitting something - in the autocannon's case, this is used for a smoke effect. Try copying the autocannon's "bullet" over to your gun and making it fit into the round - you'll find you suddenly have one very fierce handgun. Doing this is as simple as pasting the .ini definition over (above your round), and where the Round defines its own MOPixel, you want to instead tell it it is now using an AEmitter, and give it a CopyOf of your newly acquired explosive AEmitter definition.

If you rename it, repath it to your sprites and sounds, you have performed your first of many shameless thefts - something completely normal to do in the CC world. Nobody truly sits down and writes anything from scratch, it would take too long. Instead, you copy, rename, and redesign. Once you get the hang of things, you will find you can turn your pistol into a sniper rifle very quickly, and that sniper rifle into a machine-gun.

It's copies all the way down, and now you know how.

Post comment Comments
Sunw5w
Sunw5w - - 1 comments

what about these?
AIBlastRadius
AIFireVel
AILifeTime
Loudness
RecoilTransmission
ShellEjectAngle

Reply Good karma Bad karma+1 vote
iLagSoUhax Author
iLagSoUhax - - 1 comments

thank you for pointing those out, i've edited the article to include them. Should also add that the guide may be very mildly outdated; i've edited some offending parts of the guide to be more up-to-date, and will fill out any properties that i may have missed along the way.

Reply Good karma+1 vote
Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account: