Competitors.db Editing

For a long time, I’ve wanted to tamper with the competitor companies in Automation. Now that we’ve recently got the sankey chart in Campaign mode, we actually have some visibility of the competition’s company names and individual trims for the first time ever, so I figured now was as good a time as ever to start cracking.

I’ve been able to do a few small things so far:
-I can add cars to an existing company!!! This means you can, very awkwardly, compete against player cars! They don’t keep their appearance in thumbnails though.
-Change the name of an existing company
-Remove cars from an existing company’s lineup
-Learn a little more about how the competition works
-Probably cause a couple game crashes
-I have NOT ruined any Sandbox.db or campaign save files, so that’s good!

I’m still stumbling around in the dark though. In short, I’m creating this thread to share my progress now and in the future, and look for hints from anybody else who wants to take a crack at this. I’m a complete SQL noob so I’m learning as I go.

My big goal right now is to add a company from a campaign save file (or a sandbox company) into the list of competitors. However, I haven’t been able to get it to work. I’ve seemingly added my new company to all of the relevant tables, but it never appears in the list of companies in game. Just while making this thread, I managed to get player-made cars to appear though!


In this picture I replaced the cars from one of the Fruinia FamilySmall companies with cars from my campaign save file. This means we can make a campaign where you can directly compete with another person’s car roster.

My other findings so far:

Cars and companies are composed of a LOT of different, interacting tables. Every entity in the game, such as companies, models and trims, has UID (Unique ID). This is called a UID in its own table or something like a CUID (Company UID) or TUID (Trim UID) if it’s referenced in another table.

These tables all reference each other and have foreign key constraints (you can’t have a blank register which is supposed to reference a UID in another table, you can’t delete a UID which is referenced somewhere else).

There’s also a LOT of tables in Competitors.db which are modeled after a player save file. Many of them are blank, and a few of them seem to reference a placeholder player type company called Stormwell Motorworks, which is the only company to have factories, but it has no cars and doesn’t appear in game. For example, the tables for dealership levels and marketing exist but are blank. Competitor cars also have spaces for data about things like paint and fixtures, which are blank or filled with default values.

Just cars consist of the following (non-empty) tables, in approximate order of dependency:
Model
Family
Variant
Trim
TrimResults
CarFacelifts
TrimSlots
EngineResults
EngineCurves (IDK if this one is important, but the competitor cars have data here)
CompetitorTrimCostInfo
CompetitorVariantCostInfo

The last two DO NOT exist in player save files, and show an ET, PU, and M$ cost for trims and variants. In my case I filled them with some estimated data, I don’t actually know how to get correct data from the other tables.

Companies consist of the following tables
Companies
CompanySize (not in player save file, gives numbers for size at various years)
CompanyProfile (not in player save file, designates a type such as “Family Small”)
CompanyAwareness (for each market in each country at various points in time, this is a huge table)
CompanyPrestigeAndReputation (also over time)
CarProjects (associates a model with a company and a date, called Internal Days but it looks like a year)
CompanyTrims (associates each trim’s UID with a CUID, again not in player save file so I had to construct this)

Incidentally, I believe this list is exhaustive, because I kept deleting these tables until I stopped getting foreign key constraint errors when I tried to delete a UID from Companies. So I don’t think I missed any.

That leaves me stumped as to what I might be doing wrong. (Edit while writing this: I missed CarFacelifts table lmao). Well, I still don’t know why my company won’t appear, but I can make cars appear in an existing company.

We do have a few findings from looking at the Competitors.db. First, the way people talked implied that all companies chose from a list of all cars, but instead it seems like every trim is associated with a company. I don’t know if each company produces all of their cars or if it’s randomized during each campaign in some way, but if a model belonged to FamilySmall 3 Fruinia in one playthrough, that model will always belong to FamilySmall 3 Fruinia.

We can also see some of the ways that competitor companies behave differently than player companies, such as the fact that they have a ‘size’ number in lieu of both factories and dealerships but they DO have a full map of awareness just like the players do. They also slowly grow over the course of the game on a fixed track, it doesn’t seem like the economy, competition, or anything else would alter their size.

There’s also a couple other tables I haven’t messed with yet but they look like they should do something. Country unlock years are governed by a table, and there’s a table called DemographicModifiers which seems to determine the country demographic tastes, so I could make everybody in Dalluha love small cars instead of big ones or something. There’s also a lot of stuff that is NOT in here, like emissions and safety dates, or demographic sizes.

My Next Goals
The #1 thing I want to do is make a script which lets me dump a player save file into the competition with a few clicks. This will be much easier if I manage to add companies instead of merely overwriting them as well. I also need to learn SQL better so I can handle some of the tables that need new data created instead of just INSERT commands, I’ve been manually pasting them in the SQLite GUI.

Hit me up here or on the official discord if you can help me figure out the next steps, or want help getting as far as I have on your end. I might want to collect some save files to try playing against too.

5 Likes

My TODO list now:

  • Get new companies to appear in-game. I hope this isn’t hardcoded to UIDs or something silly. (Difficulty: ???)
  • Write a script that generates info for tables not in save file (Difficulty: SQL 101 but I’m dumb)
  • Get accurate cost information for CompetitorTrimCostsInfo and CompetitorVariantCostsInfo (Difficulty: Hard)
  • Get thumbnails to work (I imported them successfully, but they might just not be used by the game right now) (Difficulty: Wait for implementation?)
  • Learn how CompanySize works, maybe make a formula to estimate it backwards from trim sales or factory sizes. For now though the best bet will be to just copy it from existing companies.
2 Likes

You’ll probably be working with the team in about a year or so.

Dope shit.

Companies are not hard-coded, so you should just be able to add them to the Companies table, then point your car projects towards their respective companies with the CUID field.

Thanks! This is good to know. I am still definitely doing something wrong with my new company because it doesn’t appear on the market list at all (and I know that a company will still appear if it has no valid cars). I’ll have to keep digging.

Edit: Does defaultCompanies.csv have something to do with it? EG, are only some of the companies found in the Companies table used in the game based on this list?

1 Like

I assume you are using https://sqlitebrowser.org/

What you could do, is use the Attach Database function to attach your Sandbox or Campaign database to the Competitors, e.g. as Player

You should then be able to do various in order INSERTS

So something like

INSERT INTO Companies SELECT * FROM Player.Companies;
INSERT INTO CarProjects SELECT * FROM Player.CarProjects;

And any other customization you might want, e.g

INSERT INTO CarProjects SELECT * FROM Player.CarProjects WHERE MUID = “Foo”

I should add, for the foreign key hierarchy should be something close to this

Companies
	Factories
	Projects
		Facelifts
		Models/Families
			Slots
				Variants/Trims
					Trim/Engine Results
				FactoryConfigurations
					FactorySlots

Although the AI/Competitor Companies don’t have factories, their size is determined by the size you talked about in their config.

Yes, this is what I’ve done for most of the tables listed in the first post. There were a few tables not present in the player save file as well, such as CompanyTrims and CompetitorTrimCostsInfo. I’m actually not sure why CompanyTrims needs to exist since each trim is part of a project which is already associated with a company, but I made sure to fill it out anyway. (I guess if there was ever a feature where you could buy the right to produce a trim from another company, this table would be necessary).

I didn’t figure out how to populated CompanyTrims without the GUI though. For that I need to add the same CUID in front of each TUID, maybe I need to make that as a view first and copy it back or something. It’s definitely doable though.

As for CompetitorTrimCostsInfo, I just made up some cost numbers. I didn’t find where the player trims’ final ET, PU, and M$ were stored, presumably because they depend on your engineering sliders. On further investigation, this is stored in the table TrimEngineeringInfo (and VariantEngineeringInfo for engines), so I can pull it from there. That table is of course blank for competitors but it’s used in the player save file.

I think I’m missing something that’s necessary to make my new, custom company appear instead of modifying the existing ones still. The companies are only directly referenced in (as far as I’m aware)

Companies
	CarProjects
	CompanyTrims
	CompanySize
	CompanyProfile
	CompanyAwareness
	CompanyPrestigeAndReputation

I made sure my new company was referenced in all of these, though I had to make up some data for CompanySize. It might be that my company isn’t appearing because that data I made up, or something else, is invalid. CompanySize in particular has a ton of data points and I tried making just a few, so maybe I’ll need to copy another company’s entire list of entries in that table.

Otherwise it could be controlled elsewhere, for example if defaultCompanies.csv located in Content\GameData\Camso\cars causes only a certain number of companies to be used, or there’s a setting somewhere else to that effect.

1 Like

You should be able to safely ignore CompanyTrims, in fact your bringing that up reminded me to make a task to remove it.

It is a legacy from before competitors having Projects and Facelifts like a player company.

CompetitorTrimCostsInfo and CompetitorVariantCostsInfo isn’t critical to market/demographic calculations. It is used for feedback to the player during car design. I.e. feeding the comparisons on the left Side stats during Engine/Car Design.

CompanySize and CompanyProfile will be needed.

CompanyAwareness and CompanyPrestigeAndReputation won’t be needed in the competitors database.

Whew, I got my company to appear! Turns out my problem was that I didn’t have a complete CompanySize table. Somehow I got it into my head earlier that the CompanySize had different amounts of lines for different companies, but that must have been the PrestigeAndReputation table or something. In fact every company gets exactly 961 lines, and if you’re missing some, you will have a problem.

I also skipped some of the tables Zeussy said were deprecated this time around, that’s good to know about! Especially since correctly filling out trim and variant costs would have been a little complicated.

There is one issue that makes it different from competing against a player as I imagine it: I have noticed that it isn’t selling all of the trims all of the time. I assume this is by design, it only produces some of the trims which are available at any time. This is probably based on both the target demographics of the trims, and the size of the company. It also seems fairly deterministic which makes me wonder if some of the trims in the competitors.db are destined to never be used.

In my ideal scenario, I would have every trim from a player’s save file active when it was active in the save file. That might not happen, but I will also have to do some experimentation later on whether the declared target demographic matters. I know a lot of people leave the same target demographic on their trims.

For anyone looking to follow in my footsteps, I have a complete code for SQLite which will allow you to add your save file to the competitors. Back up your competitors.db first. Simply open the competitors.db file, attach your save file under the alias “savegame” and this will work! You may want to change the name of the company whose size and profile is copied.


--Insert companies and car data. CompanySize and CompanyProfile still have to be done after this.
insert into Companies
	select * from savegame.Companies;
insert into Models
	select * from savegame.Models;
insert into CarProjects
	select * from savegame.CarProjects;
insert into Families
	select * from savegame.Families;
insert into Variants
	select * from savegame.variants;
insert into Trims
	select * from savegame.Trims;
insert into TrimResults
	select * from savegame.TrimResults;
insert into EngineResults
	select * from savegame.EngineResults;
insert into EngineCurves
	select * from savegame.EngineCurves;
insert into CarFacelifts
	select * from savegame.CarFacelifts;
insert into TrimSlots
	select * from savegame.TrimSlots;
insert into TrimEmissions
	select * from savegame.TrimEmissions; --Pretty sure this isn't actually used by competitors
insert into CarThumbnails
	select * from savegame.CarThumbnails; --This doesn't work right now but I'm leaving it in anyway
--CompanyAwareness, CompanyPrestigeAndReputation are both populated by competitors, but I'm told they're not necessary


--Now we are going to copy CompanySize and CompanyProfile from FamilySmall 3 Fruinia
--Change the two references to "FamilySmall 3 Fruinia" to the name of any other company you can see in the sankey chart if you want. It should affect the number and type of trims produced.

insert into CompanyProfile (CUID, Profile, ColourHex)
	Select (select uid from savegame.companies), profile, ColourHex --ColourHex can be a hex color you choose instead
from CompanyProfile
	where CUID = (select uid from companies where name = 'FamilySmall 3 Fruinia');
		
insert into CompanySize (CUID, Year, Size)
	Select (select uid from savegame.companies), Year, Size
from CompanySize
	where CUID = (select uid from companies where name = 'FamilySmall 3 Fruinia');
	

As a side note, if you ever wish to disable a company, the most expedient way to do so is probably to remove its entries from CompanySize. This will stop it from appearing in game, and is faster than actually deleting it or its cars because you have to go bottom up in order of dependencies.

Now that I’ve reached this step, I would like to ask for some save files! If I can get several save files which have played the whole timeline, we can playtest what it’s like against human-made cars. Edit: Actually, sandbox companies might be possible to import as well. I’ll have to check if they have projects and facelifts.
Edit 2: The last couple paragraphs will also not work on a sandbox save file without some alterations. The simplest way would be to specify a single company name to copy for at a time, and run that section again if you want to do multiple companies.

3 Likes

I have noticed that it isn’t selling all of the trims all of the time. I assume this is by design, it only produces some of the trims which are available at any time. This is probably based on both the target demographics of the trims,

We select competitor trims, by getting the latest facelifts of the last 15 years, and selecting Unique Target Demographic Trims per Facelift.

So if you have a facelift with 3 trims, all with the same target demographic it will just use 1 of them.
If you have 2 facelifts, with all trims the same target demographic. You will get 2 trims, 1 from each facelift.

The company size data only was used on initial generation of the competitors.

1 Like


THUMBNAILS ARE WORKING!

The thumbnails simply have to be a part of the save game you are currently playing. If you have your target save game open in SQLite, and the competitor company’s savegame (competitors.db already containing your competitors) attached under the alias ‘savegame’, the script you need would look like this:

insert into Models
	select * from savegame.Models;
insert into Families
	select * from savegame.Families;
insert into Variants
	select * from savegame.variants;
insert into Trims
	select * from savegame.Trims;
insert into CarThumbnails
	select * from savegame.CarThumbnails;

All those tables are necessary because of the dependencies.

With this, I’m really eager to get a player company or two into my current youtube let’s play series. I think being able to have a rivalry with a human opponent whose cars you can see would add a lot of fun factor.

It is unfortunate that I can’t just hand out a competitors.db file to other people who want to see this though, since they need to start with a modified save as well (and edit it again every time they want to start with a different company name, starting country, etc).

In other news, I’ve been exploring CompanySize a bit. I’m told that it determines both the number of models which can be on sale at a time, and market awareness.

With regards to market awareness, it looks like every company has only one awareness number for each country, and it’s the same for all markets in that country. If I want to compete against player companies, I can’t give them the actual factories or production numbers they have, but I can try to correlate awareness to size and generate a size table for the company that gives them an awareness equal to that of their best market during their actual campaign history. I’ll need to improve my skills to pull that off, but it should be possible.

It looks like the number of models in a company is determined at generation, with larger companies having more models. I’m not sure how they decide when to stop selling an old model, and whether a new model will replace an old one or not. But, I’m hopeful that a competitor company will sell all models available to it until they become competitive, because I know sometimes player companies can have a wide variety of models while still being comparatively small.

image
Besides actually editing the competitors.db, I want to learn more about how the competitor companies work. I might want to work on charting more sizes, and correlating them to awareness etc. I think I’m just going to have to look at in-game awareness because size is probably not correlated to the now-unused data in the CompanyAwareness table.

That said, for now I can still just copy a company’s size curve or make one up, so I’m definitely ready to get my hands on some people’s save files and start seeing what gameplay is like with human competitors. I’m curious how much the competition really makes an impact… sometimes in campaign right now it seems like most markets are under-served, but I haven’t even played later into the campaign in the last few builds.

Some more findings:
Having talked a little with Killrob, company sizes are sinusoidal. They have a randomized phase (their peak could be anywhere from 1940 to 1980, although I think it’s biased towards later peaks?) and a zero-point which is equal to the company’s stated size number.

This chart is the size of all Archana companies in the current Competitors.db. This will be randomized whenever competitors are re-generated for a later version though. (Incidentally, you can do this yourself at any time through the F9 debug menu. I’m told it takes hours though.)

Killrob also provided this chart as an example of a company with an early peak. The red line illustrates model slots, the company generates with a number of models equal to size, rounded to the nearest integer.

I’ve also been trying to correlate company size with awareness (home country only). I’ve learned that it does not vary with year, or market, only size. Foreign countries are reduced by some amount based on unlock year. (Edit to clarify- X axis is Company Size, Y axis is Awareness %)
image

Raw Numbers
0.1	2.9
0.2	4.6
0.5	8.5
0.8	11.7
1	13.5
2	21.5
3	28.2
4	34.1
5	39.6
6	44.7
7	49.5
8	54.2
9	58.6
10	62.9
11	67
13	74.9
15	82.4
20	99.8

It’s been way too long since I last struggled through math class for me to remember what the formula for this line with a decreasing slope probably is, but I’ll figure it out later or just ask @Killrob. Or I can be lazy and say that Size = Awareness * 20 :wink:

Then I can put together a formula that copies into the CompanySize table based on awareness history (optionally since sandbox companies don’t have this) for the most accurate representation of player competition.

With a lot of other peoples code help from Stack Overflow, I’ve managed to create an SQL query that generates a CompanySize table. It’s still using a placeholder linear calculation between size and awareness (I settled on 16). I definitely think basing it off of awareness captures the player companies tend to grow better than copying an existing company.

It’s based on the single highest Market Awareness you have in any market and any country each month, but the result of course when your company is a competitor is that will be the awareness in all markets in your home country.

(Side note… why oh why do you use integer InternalDays in some places and float Years in others? Especially when the only real unit of time in the game is a month, which could just be its own integer? Why 1946.0833333333 instead of 0 months since game start???)

insert into CompanySize (CUID, Year, Size) 
select CUID, ((internaldays-4321.0)/(360))+1946, MAX(AwarenessTotal*16) from savegame.companyawareness
group by InternalDays

This would replace the paragraph which copies company size in the big script from earlier.

In a similar vein it makes more sense to replace the paragraph that generates company profile with one that relies on user input. Knowing that market awareness is equal for all markets, and the number of models in the database seems correlated with company size (rather than the company picking from a larger list and leaving some models un-used) it’s very possible that the Profile column doesn’t affect anything after competitor generation, which is done already for AI companies and moot for player companies. Color shows up in the sankey chart, but you can pick that on your own right?

Actually, just now I tried replacing all the Profile entries with a rude word and it didn’t break anything either. I could probably even leave it null but I won’t do that for now.

insert into CompanyProfile (CUID, Profile, ColourHex)
	Select (select uid from savegame.companies), 'Generalist', 'FFFFFFFF'

Notably the color hex includes an alpha (Unreal thing?) but if you set it to less than FF it looks goofy.

While playing around with CompanySize I learned that companies appear in each month they have a size entry and disappear in any month where they don’t have a size entry. They can even have a gap in the middle and suddenly re-appear. AI companies have entries going back to 1940, but I don’t think this has an effect on gameplay. I tried deleting entries from before 1946 and it didn’t seem to affect anything.

What's the point of all this?

Except for wanting to come up with a better equation for size based on awareness, I think I’ve pretty much completed my goal of figuring out what’s necessary to add player companies to the competitor database. That’s the main thing I wanted to do when I started.

The other thing I hoped to do was tamper with demographics so EG I could make a challenge setting where some demographics are larger or smaller, or only a few demographics are included in the game. It looks like these are all in uasset files which can’t be read without row information that’s stored somewhere else, so that is on hold for now.

First of all, I’ll have to gather some save files when they’re forthcoming (I don’t think many people have played a full campaign on openbeta yet) and make a competitors.db to actually try some gameplay against human-made cars, which should make for stiff competition.

The next step would be to make a utility which automates the process of setting up both the competitor.db and save file with thumbnails. The process of opening the database in SQLite, attaching the save file, running the script, attaching the other save file, and running the other script, is not fast, convenient, or foolproof. It seems like every programming language under the sun has an SQL API, so I guess I really just have a pick a language and go for it.

Pretty much all of my experience so far is in Java, but that seems out of fashion now so maybe Python, or C++. (The latter option means it’s already fast so nothing has to be rewritten later :wink: ) Don’t hold your breath, but maybe I’ll create a tool to make this easy for people later.

If you have Java experience, switching over to making an app in C# shouldn’t be much of a jump. Grab Visual Studio Community, and have a play. It appears Microsoft have a SQLite library that can be readily imported: Overview - Microsoft.Data.Sqlite | Microsoft Learn

I’ve also made a Ticket to change our thumbnail loading to do a search in the competitor’s DB.
We should be able to add support for switching/modding the competitors db. I’ll have more of a ponder and look at things to see if we can readily do a merge of several competitors db’s at once.

Of course the more companies and more trims the slower the month-to-month calculations will become.

I decided I wanted to get a closer look at some of the competitor cars. Since we can’t directly view them from the campaign market screen, I just imported them and their companies into my sandbox. :wink:


Well, I must have missed some important information, or the competitor cars don’t have it, because I got a lua error (about engine peak power) whenever I open one and all the trim options are locked. But I got what I wanted, which is the ability to see all of their engineering options in a presentable way. If I’m wondering how a car in campaign is beating my stats, I can see it now. I can also view a company’s whole lineup.

This led to an odd finding!
First, I noticed that of the two SportUltra companies (SportUltra 2 Fruinia and SportUltra 2 Dalluha), neither of them have any cars at all! Looking in Competitors.db revealed that both companies have no CarProjects associated with them. Therefore, they make no cars!

select * from models where UID not in (select MUID from CarProjects)

While those are the only two companies with no cars at all, I found 34 ‘orphaned’ Models, which do not have a CarProject and therefore are not associated with a company, and will not appear in the game. This includes 14 Super and Hyper models, probably the ones which those other companies were supposed to have. Only 3 Super and 1 Hyper model actually have CarProjects!

Besides those, the remaining 20 orphaned models include a lot of Heavy Utility, Offroad, and L.Sport P., but none of these are the majority of the models in their target market like with Super and Hyper.

One last thing, I’ve managed to put together a script which gets thumbnails from a modified competitors.db which includes them… as well as the chain of dependencies they rely on. This means if I want to give someone a modified competitors.db, they can add the thumbnails to their save file without having one or more save files which I originally took the thumbnails from, and also without adding ALL the Families/Variants/Models/Trims to their save file. Might have been able to make this easier to read with Join instead of these nested Selects but it works.

insert into savegame.models
	select * from models where UID in (
			select MUID from trims where uid in (select TUID from carthumbnails));

insert into savegame.families
	select * from families where uid in 
		(select FUID from variants where UID in (select VUID from trims where UID in (select TUID from carthumbnails)));

insert into savegame.Variants
	select * from variants where UID in 
		(select VUID from trims where UID in (select TUID from carthumbnails));

insert into savegame.trims
	select * from trims where UID in 
		(select TUID from CarThumbnails);

insert into savegame.CarThumbnails
	select * from CarThumbnails;

Edit:
Another finding today:
It’s an issue that Competitors will not sell trims with duplicate target demographics in the same facelift, since players often neglect to set different target demographics. I’ve learned that the target demographic is stored in the TrimSlots table. It looks like EDEMOGRAPHIC::ED_CITY or something like that. You can fill this space with any garbage and it doesn’t cause a problem, it just has to be unique. I tried just going in there and setting them all to 1, 2, 3 and so on. This solved the problem that some trims were not selling but created a new problem. Now, trims from an older facelift would be on sale at the same time as the newer facelift. That’s not ideal!

It also makes me wonder about the conditions which cause a facelift to stop being on sale. Apparently, a newer facelift having trims with the same target demographic is one condition. If I had a convertible in Facelift Mk1, and removed in Facelift Mk2, I guess the Mk1 Convertible is supposed to stay on sale? When do Models get removed from sale, is there a hard limit in years? Can I sell two models with the same target demographic? I might have to experiment to figure this out.

Anyway, I guess the way to solve this is to make a script that finds duplicate target demographics in the same facelift. Luckily facelift FUIDs are in the trimslots table, so I can easily group by them. I’ll have to do something like, count the instances of each target demographic within each facelift, and rename only the duplicates. That will take a bit of doing to figure out.

And just for the purposes of my notes, I have two more outstanding issues. First, companies disappear when they have no size data, so I will have to figure out how to get a list of years with no size data and add them, preferably without adding any data before the game start as well. Something as simple as select distinct doesn’t quite work since the years are repeated for other companies in the same table.

Second, my estimate of awareness is still an estimate and should be able to get it exact, if I can figure out the equation with governs the relation between size and awareness.

1 Like

Changing a company’s lineup (and possibly name) to match its lore over time? This is just what campaign players wanted!

Alright, haven’t touched this for a while but I got back into it after getting back from vacation. First things first, big thanks to, I assume Caswal, for going ahead an implementing the feature for thumbnails to be read from the competitors.db. That eliminates the need to add thumbnails to each save file that will be playing with modified competitors, saving some hassle and filesize bloat for users.

Second, I originally wrote my script with only a finished save file in mind. But, as I have been slowly going through my video campaign, I realized that being able to update it with your new cars after every play session is a lot more appealing. The below script checks for duplicates, so you can add cars from a newer version of the same savegame without issues.

Third, since I last posted in here, I have just reverted to stealing company size data again, as a solution to the fact that I can’t grab awareness for a whole save file since it is gets deleted after a few in-game years (I guess the file size bloat otherwise would be a lot).


/*HOW TO
This script is for adding your cars to competitors.db. If you have a Competitors.db and want thumbnails, you need the other script!

Find your Competitors.db in SteamLibrary\steamapps\common\Automation\UE427\AutomationGame\Content\GameData\Camso\tycoon
  Or go to your stream library, Browse Local Files for Automation, and follow the above file path
Make a backup copy!
Open Competitors.db in SQLite
Next, click "Attach Database" on the top bar of SQLite
Find your save file in %localappdata%\AutomationGame\Saved\UserData\Campaign, open it, and when asked what you want to call it, enter 'savegame' (no quotes)
Next find the "Execute SQL" tab, it's one row BELOW the Attach Database button
Copy this script into the space there, and run it! (F5)
Before you close SQLite, click "Write Changes" on top!
Now your cars are part of Competitors.db.

If you want to add cars from sandbox, select that instead of your campaign save game, and make the changes marked below. You will need to know your company name.

PRO TIP: If two trims in a facelift have the SAME TARGET MARKET, then ONLY ONE WILL BE USED! Set different target markets for each trim!
*/

--Insert companies and car data. CompanySize and CompanyProfile still have to be made from scratch after this.
insert into Companies
	select * from savegame.Companies where uid not in (select uid from Companies);
insert into Models
	select * from savegame.Models where uid not in (select uid from Models);
insert into CarProjects
	select * from savegame.CarProjects where uid not in (select uid from CarProjects);
insert into Families
	select * from savegame.Families where uid not in (select uid from Families);
insert into Variants
	select * from savegame.Variants where uid not in (select uid from Variants);
insert into Trims
	select * from savegame.Trims where uid not in (select uid from Trims);
insert into TrimResults
	select * from savegame.TrimResults where uid not in (select uid from TrimResults);
insert into EngineResults
	select * from savegame.EngineResults where uid not in (select uid from EngineResults);
insert into EngineCurves
	select * from savegame.EngineCurves where uid not in (select uid from EngineCurves);
insert into CarFacelifts
	select * from savegame.CarFacelifts where uid not in (select uid from CarFacelifts);
insert into TrimSlots
	select * from savegame.TrimSlots where uid not in (select uid from TrimSlots);
insert into TrimEmissions
	select * from savegame.TrimEmissions where uid not in (select uid from TrimEmissions); --Pretty sure this isn't actually used by competitors
insert into CarThumbnails
	select * from savegame.CarThumbnails where tuid not in (select tuid from CarThumbnails); --This doesn't work right now but I'm leaving it in, in case an update uses it


--If your company is a sandbox company, add a name for your company in the first select statement below, like in the bottom select statement
--Size is copied from Generalist 6 Gasmea by default right now because it is the largest and player awareness tends to be high, but you can choose another company
Delete from CompanySize where CUID in (select uid from savegame.companies); --This prevents duplicates

insert into CompanySize (CUID, Year, Size)
	Select (select uid from savegame.companies), Year, Size
from CompanySize
	where CUID = (select uid from companies where name = 'Generalist 6 Gasmea');

/*Profile probably does nothing. Leaving it null still feels like bad juju.
Color appears in the sankey chart. Last two FF is alpha channel, leave it FF.
Use an online hex color picker and set the first 6 characters to whatever you want.*/		
insert into CompanyProfile (CUID, Profile, ColourHex)
	Select uid, 'Generalist', 'FFFFFFFF'
from savegame.companies
	where not uid in (select uid from CompanyProfile);
--IF YOUR COMPANY IS A SANDBOX COMPANY:
-- Replace the the above line with this one and the name of your company:
-- 	Select (select uid from savegame.companies where name = 'sandbox'), 'Generalist', 'FFFFFFFF'


This script is not exactly elegant but it works. I still haven’t figured out how to identify or delete duplicate rows in CompanySize (since I’m looking for rows where multiple columns match). I’ve tried some stuff from stackexchange, but only come up with error messages and disappointment so far. Either DB Browser doesn’t implement some commands people are using or, more likely, I’m incompetent and missing something. My hacky solution is to delete the CompanySize data for the player company every time the script is run, and copy it again.

Anyway, you can now run this script repeatedly on the same company without errors, and it will include and new cars.

Some more fun file analysis time!

I mentioned before that I wanted to get a crack at the uasset files in the GameData\Camso\Demographics folder, since the file names imply they control how the game’s demographics work. Earlier, I got them open in the unreal editor, but couldn’t really do anything because they’re missing row data. Well, I’m not sure exactly where it’s located, but that RowData is somewhere in the Unreal project from the Automation mod tools which I downloaded since I made a fixture mod earlier. If I open them through there, it works!

Well, most of them have RowData anyway. This one might still be exclusive to Isaac’s computer. You couldn’t think of somewhere better to save it than your desktop? :wink:
image

For the ones that do have RowData, we can get a look inside. Apologies for the GIANT stitched screenshot, but this DemographicMatrix tells us some stuff that I don’t think we can see in the game, such as how many kilometers a given market drives in a year, which is used to calculate affordability. Other interesting notes is that every market has a “Budget type” of EB_G or EB_H, the latter of which is used by all the ‘budget’ demographics and some utility. Also, in addition to everything else, every market is has a “Car Class” which is one of “Budget”, “Normal”, “Premium”, “Luxury”, or “Industry”. No idea what that does that isn’t covered by all the other columns here.

Sadly, I can’t really edit them. These uasset files seem to be used at build time only, not loaded when you start the game like the competitors database. I tried editing some values in this and other files, but nothing shows up in the game. So, I can’t tweak demographic or country behavior, lock off demographics, or any other fun stuff. We can look at these files for hints about unexplained game mechanics though.

RegionFuelData explains how fuel availability works in, if we’re being honest, a more clear way than the in-game fuel availability chart. There’s just a fuel availability given at each decade for each fuel type. In game it gradually approaches the next decade value on a month to month basis.

There a file like Size_Export_Archana for each country. It just has a Size Factor and a Year Modifier, which is the unlock year. This suggests that growth rate of the markets is the same for each country with just a factor applied, so you couldn’t have, say, Family growing Hetvesia at the same as it stalls in Gasmea and is replaced by SUV’s. I think.

StatScoring is confusing to me, but seems to affect the way in which stats give desirability, and define when “Low Stat” penalties should occur.

RegionsData is particularly interesting. Companies have modifiers to Interest Rate and Credit Ease… I’m not clear if this is for the purpose of the player taking out loans, determining the budget of car buyers, or both. I also assumed that country descriptions like “Fruinia has steep hills, narrow streets, and good weather” in the campaign setup screen were just flavor, but they’re actually numbers assigned to the countries. I guess rather than being a flavor reason to explain why Fruinia has Sportiness taste, it’s a consequence of these stats.


Determining taste stats like Drivability, Comfort and Sportiness mathematically by this many different factors seems needlessly complicated compared to just choosing some numbers and justifying them with flavor text later, so I’m absolutely certain this was Killrob’s idea. :wink:

We can also see some stuff like “Driver Skill”. Gasmea has the second worst (0.3) just barely ahead of Dalluha (0.2). Well, if Gasmea is supposed to be like North America… okay, maybe. But I’ll have to actually visit europe some time before being so sure Fruinia deserves 0.9, lol. (I think this is mostly just inverse to Drivability taste though.)

There’s also an Econ Start and Econ End… if this controls economy size, it looks like Dalluha is the only country whose economy gets worse through the game, while the others grow by various amounts. Fruinia also has a Displacement Tax Year of 1984 while the rest of the countries have years after the game end, but I don’t think this does anything right now. There is a Safety Regulation number as well, which I think is deprecated by the RegionsSafety table, which has the safety minimums that are actually used in the game.