Saturday, April 3, 2021

Project Breach #4 - "Equipment, Cover Objects and Enemy AI Start"

 Project Breach #4
"Equipment, Cover Objects and Enemy AI Start"


Visuals
There's so much to this update it was hard to pick a place to start.

First, there's a new grass texture, which is probably the 8th time I've remade it, but this is the first time where I'm actually satisfied with how it turned out.

And secondly, there's now a cloud effect which you can turn on in the map editor's new "Environment" section. Here's those two things together:




The clouds are generated from a shader which uses procedural noise so that it never repeats. In the map editor you can adjust all sorts of settings so it doesn't need to just represent clouds. Want to make an apocalyptic map with green chemical filled air? You can!






After that I worked on making so that pawns bob while moving. Even though this games art style was inspired by Rimworld, I think pawns bobbing adds a bit more flavor to their movement that's missing from that game & similar ones (Like Prison Architect). Movement bobbing is a system I developed for Black Company and I thought it'd do the job perfectly. What's cool about it is that the bobbing can change speed based off of how fast the pawn is moving which can be measured client-side by measuring the distance between where the pawn was the last frame vs where they are now. That way clients can all get a similar bob without having to send any data over the network and the faster a unit moves will automatically result in matching bobbing.

I also made so pawns will adjust what direction their weapon is aimed based off of which direction they're moving.




Later in the update I'll be talking more about the gameplay aspects of equipment, but there is now equipment the pawns can use such as body armor. Because I wanted pawns to be able to show what equipment they have on, I created some new base texture atlases for pawns to use:





And here's what the three equipment texture atlas looks like (Body Armor, Helmet, Guerilla Vest):






It was important for me to make so that equipment could be shown on pawns so that way you can tell at a glance what you're dealing with when you see an enemy.

Next I added damage popups:




If you're wondering why the players pawn is taking 3 damage while the enemy pawn is taking 23 damage, it's not because player pawns get a buff to take less damage, it's because the enemy's armor is visual only and gives no armor & they're using a worse weapon. This is how the game is intended to be balanced, so that if you went up against someone with equal equipment, you'd take just as much damage as an enemy. But enemies will likely always have much worse equipment with the exception of potentially specialty units. This is important to note because I want to make it clear, your pawns do not get a cheat "Take less damage" buff. And in the campaign, as well as in the multiplayer, you will be able to customize the equipment your pawns have before going into missions.

And finally for visuals, I created a new barbwire fence texture (Although this is I think the first time I've shown the barbwire fence in a blog post):




Gameplay
Pawns can now be given an attack order by right clicking an enemy pawn. This will make your pawn automatically run to them & attack them once they're able. This order will automatically finish when the pawn is either dead, and in the future, if the enemy pawn is no longer visible due to fog of war / sight. Pawns can also theoretically be given an order to attack a position (This is helpful for things like shooting through a wall you suspect a target might be behind), although this won't be able to be tested until I begin implementing the player UI.

I've also made so that if a pawn fires a bullet, and a friendly pawn is within 2m (2 tiles) of that bullet, it won't damage them. This lets you stack pawns up to 2 next to each other without having to worry as much about friendly fire.




Pawns can also now be headshot. Because the head of pawns is so large, if I made this calculation solely based off of where the bullet hit it's likely 50% of all shots would result in a headshot which is pretty unbalanced. So I made so if a bullet hits the upper half of a pawns body, there's a 10% chance it'll be a headshot. I can play around with that value more with testing. A headshot will result in the projectile dealing 200% damage.




This leads me perfectly into passive equipment. Equipment the pawn wears like body armor is referred to in-code as 'passive equipment' because it's things the pawn equips that just provide a permanent buff until unequiped and which the pawn can't do an action with. Right now this means armor but in the future could also mean things like extra ammo capacity, extra health, or any number of other buffs.

Passive equipment have a flag in their file called "ArmorEffectsTotal". Any equipment which has this on will add its armor value to the pawns total. The total armor value of a pawn determines how much damage they'll take normally.

How much armor protects you is equal to the value of the armor. So if you were going to take 30 damage but you're wearing armor totalling 20, you'd only take 10 damage. The exception to this are headshots which only care about what armor you have in your pawns head slot. I personally make so that helmets will have "ArmorEffecsTotal" set to false because I don't think the armor value of a helmet should effect how much damage you take from a body shot, but modders are free to turn that on.




If you're wondering why the guerilla vest has "ArmorEffectsTotal" set to false even though it has an armor value of 0, it's because then the game won't even try to check the armor when equipping & unequipping, which is unnoticeably slightly faster for the CPU but I figured I might as well.

Cover Objects
There are now three-ish new cover objects in the world!

Cover is of course an important part of a tactical shooter. But cover needs to be more than just hiding behind a wall or pillar, there need to be things that you can stand behind and be protected while still being able to shoot back at the enemy. So the first thing I worked on to get that system started was sandbags:



Cover objects you will shoot over if you're standing right next to, but have a chance to block bullets being shot at from a distance. I had to reprogram the penetration system in order to achieve this.

Game surfaces was a cool idea, but I ended up getting rid of it entirely. Game surfaces worked because it was values that all things with that surface could use (All glass should be see through, all wood can be shot through, etc.) but this became a problem quickly as I found that every object needed the values at least slightly different from each other, to the point where almost every object had its own surface, at which point it sorta defeated the purpose of having game surfaces that multiple objects could share. So I moved all the properties of game surfaces to be set on each object & I completely reprogrammed how penetration works and made those values on objects instead of surfaces as well.

Projectiles now have a penetration value which must be equal to or exceed the penetration defense of an object in order for the projectile to go through. Although objects can still define % chance of a projectile penetrating. Here's what some of that data looks like on an object:




Enemy AI (Start)
The gameplay features were coming together but it wasn't exactly exciting to fight enemies who stood still the entire time and just shot whenever you got in sight. Talking with my friend Nico about it, he helped me compile a set of things the enemy AI should be able to do as well reactions to what the player does.

This is quite intimidating as I've never had to work on this sort of more complex AI logic before. The AI in all my games usually could be boiled down to "Go toward the player, attack the player when you're able to do so". I've done minor experiences on random projects with other features but nothing to fancy. The AI in order to work for this game will need to be able to do things like wander around, have patrol paths, take cover, use equipment like grenades, react to equipment the player uses such as running away from grenades, and be alerted to the players presence when gunshots start going off.

This is a lot to do and I'm interested to see how I manage. I've begun on the AI which I call "Pawn Brains". This is because in the future if I decide to make AI that can think differently, I want the user to be able to tell pawns to use different brains such as "This is the more defensive brain that cares more about being behind cover, this is the offensive rush brain, etc." but for now it'll all be using one.

The only thing AI do now is wander. I made so that they try to stay in the area that they started at, otherwise you'd end up with pawns wandering to the other side of the map. This does create some problems though, take this example:




In this example, our pawn (the light green) should stay within 4 tiles of where they start. This means they shouldn't wander outside the wall (represented by Black). The problem is that if we just randomly tell them to go to a point within their 4x4 area, they could try to path outside the wall, which would lead them to walk out the hole in the wall which is clearly a completely different area from where they should ever be (You can see the path they'd take with the yellow):



So how do we solve this problem? My first way of solving this problem created a bug. I simply measured the distance from their spawn point to where they were, and if they went greater than 4 units, forced them to stop moving & then to pick a new location to move to, hoping that this new location wasn't an invalid one. The problem was that then when they got their new order, they were still greater than 4 units from their spawn point, so it'd once again cancel their order. This means that once they wandered greater than 4 units, they could never move again.

After a few more ideas, I boiled it down to three solutions:
1) When the pawn gets out of range, have them return to their spawn point before trying to wander to a new spot again
2) Measure the length of the pawns path, since we know 1 node on the path is 1 tile, a path 5 long is 5 meters. So we know that if the path has more nodes than we want distance traveled, we should find a new tile to wander to.
3) Measure the distance between each node in the path from the spawn point, and if any return a distance greater than the wander distance, try to find a different tile to wander to.

In an ideal world, I'd go with solution 3 since it'd always be the most accurate. The problem is that distance calls are a little expensive on the CPU because computers really don't like square root operations (which is what the distance formula you were taught in school uses):

d=(x2x1)2+(y2y1)2

So because I want the game to run smoothly, I opted to not use the most accurate solution but to instead go with something faster. #2 would be the fastest but it also is the least accurate, because measuring the path could result in the pawn thinking their remaining path is within wander distance, take this scenario for example:



The pawn should never be able to access an area that requires them going outside of their wander range to reach, yet by just measuring the length of their new path, they could end up in that sort of area. In that above example, you can see the pawn walks outside of the valid area, looks for a new path, and that new path leads them into an area only reachable by having gone outside the valid area, which isn't what we want.

So although #3 is the most accurate, and #2 is the most optimized, #1 is the only one that will be accurate and CPU efficient, as it'll only require 1 distance check (Measuring the distance between the pawn & the start position).

I haven't implemented this new solution (#1) so there are potentially unforeseen consequences, but I think it'll work perfectly. Anyway, that's as far as I am with AI!

Map Editor:
While I was making the new map for testing AI, I figured I'd hammer out a feature I'd been planning to do since I first began work on the map editor. Light Sprites:




Because most ligths in the game will be 99% if not 100% sprite lights, it'd be nice for the lights to have a variety of sprites / shapes to be able to choose from. This was always intended but I'm just now finally getting around to doing it. As with everything else, these are part of the mod and you can add your own light shapes / sprites through modding if you chose to do so.

The last thing I did for the map editor was add a quality of life feature, editor grids:




These grids are 16x16 which aligns perfectly with the chunks on the map. They're mostly there to act as helpful lines, but you can toggle them off at the top left of the map editor next to where you toggle lighting.

Other Changes:
I added a loading screen which works both for transitioning scenes (Like to the main menu) as well as for loading maps. I also made so pawn dialogue can be modified from a file so that modders can make their pawns have custom dialogue or use a variety of different dialogues.

Summary
Once again, I enjoyed livestreaming on YouTube. You guys got to see me do the initial cover object system as well as solve how to make sandbags not effect other walls. Although the cover objects system has changed quite a bit since I livestreamed (due to redoing all the penetration stuff). I'd contemplated doing more livestreams but decided to leave it to 1 per week so that I'm not flooding my YouTube uploads with livestreams videos that only a fraction of people on the channel want to watch. I'm considering creating a second channel for livestreaming so that I don't flood the main channel. Or maybe I should just use Twitch but I want a recording of the livestream to exist, we'll see.

This week was more intense than most. I'm making what is quite possibly in the literal sense, record pace on the game. Several entirely new gameplay features were added, several systems rewritten, I've been working non-stop all week!

I think I've always had a problem with working too much, I'm a bit of a workaholic. And as someone who makes a living as a programming contractor working from home, weekends don't really mean anything to me which means I end up working on those too. But I'm actually feeling like I could use a bit of a break. So I'm going to try and take a few days off. It's weird to describe but I quite literally don't know what to do with my time when I'm not working. I try playing video games but there's always that feeling to get back to work in the back of my head. So it'll be hard figuring out how to take time off but I think for my own sake that I should make an effort to do so.

Anyway, as always, thanks for reading feel free to leave a comment & I'll see you in the next one!

-Blake Gillman

Extras

>Lines of code written:
20,669 lines / 236 scripts.
(+2,096 lines / +24 scripts since last update)

>"Demo Essentials" checklist:
(Done) 3~4 cover objects
Breach charge that goes through wood
(Done) Pawns
(Done) Biome Editor
Lobby UI
Squad Customization
(Done) Interactables System
(Done) Health System
(Done) Map Editor
(Done) Ranged Weapons (LMG, SMG, Shotgun, Semi Rifle, Auto Rifle, Pistol)
*Melee Weapons (Knife, Baton)
Map Entry Vehicle / Spawn
(Done) Loading Screen
Fog of War System
Main Menu
1 decent map
Player UI
(Done) Most things have some sort of SFX
Servers can be created on request (Likely, from Amazon)

I added a new item to the checklist. Before I can work on the games lobby, squad customization, even many parts of the main menu, I need to figure out how to get the game to work with amazon servers. Because it's such a big deal I made it its own separate task as it'll require a lot of time & effort & is entirely essential before I can work on many of the other demo checklist items.

Notes & Technical Extras

>Redid all IDs to be in the thousands
If you're particularly observant you may have noticed that the IDs on files are now in the thousands instead of the hundreds. This is because I found it quite short sighted to dedicate only a max of 100 per object type. The system before would be blocks were 0~100, walls 100~200, etc. The problem was once I started adding cover objects & props I immediately realized that the number of objects in a category could very easily exceed 100. So I changed the IDs of all my objects which broke all previous maps made with them but it was worth it, and I recommend any future mod developers out there also space their ID's by a thousand.

>Made sprites loaded from files have a center origin instead of a bottom left one
I fixed a problem that has been plaguing the engine from the very beginning. Sprites having their origin at the bottom left. I believed this was an unavoidable problem of loading textures from files that I was doomed to contend with and so the entire engine had to deal with this. Essentially the position a visual calculated from was its bottom left, which made scaling & rotating objects involve more math than I'd care to post. But finally I learned it was actually a problem with converting textures to sprites, and was as easy to fix as changing less than 30 characters on a line of code. So I had to spend the time to reprogram all the parts of my engine that had been programmed to deal with the bottom left origin. I believe I have everything properly converted over. I haven't redone scaling yet so objects with a custom scale don't work yet, and I also need to fix how guns rotate, but everything else has been squared off. It was worth getting everything switched over to the proper origin though as it'll save me a lot of headache moving forward & make rotating / scaling objects a lot less expensive for your PC to handle.

Blog Summary

>Notes used to create this post
Visuals:
-Added clouds effect
-Made pawns bob while moving
-Made pawn weapons face the direction they're moving if they're not targeting anything
-Redid pawn atlases to skin colors
-Added damage text popups
-Made new grass texture
-Made new barbwire fence texture

Gameplay:
-Made so pawns can be given an attack order
-Made so pawns can theoretically be given an attack position order
-Made so pawns within 2m of each other, wont friendly fire
-Made so pawns can be headshot
-Added passive equipment (Body Armor, Helmet, Guerilla Vest)

Other:
-Made cover objects (Sandbags, Barrels, Crates)
-Made so pawn dialogue can be customized in a file
-Added loading screen
-Remade FPS counter
-Got rid of game surfaces & made penetration values per-object & projectiles to have a "Penetration force" variable
-Redid ID's to be in the thousands instead of hundreds
-Made 2 new maps due to the new ID system breaking old one
-Converted entire engine to not rely on sprites having their origin at the bottom left

Map Editor:
-Added clouds effect
-Added sprite options for sprite lights
-Added grid which shows chunks & can be toggled

No comments:

Post a Comment