• Welcome to the largest (sim) racing website in the world!
    Blurring the line between real and virtual motorsports.

How to dnSpy your csharp.dll

Discussion in 'Motorsport Manager' started by Mynar, Mar 21, 2019.

  1. Mynar

    Mynar

    Messages:
    38
    Ratings:
    +2
    First off, I am a complete novice at this. I consider myself computer savvy, but am new to csharp modding. Anyways, kinda new to the game and have been hooked (to say the least) and my save game editing was only getting me so far :)
    Didnt really see anything about getting dnSpy set up for the game and have seen a few questions regarding this so here goes. People who are more knowledgeable about this, please chime in if I butcher anything.

    1) Get dnSpy, open your Csharp, right click and use the edit method option.
    dnSpy1.png

    2) On the bottom left hand of the screen (red circle) click 'Add Assembly Reference'
    dnSpy2.png

    3) From the open dialogue screen, navigate to your ...steamapps\common\Motorsport Manager\MM_Data\Managed folder and i select everything in the folder except for the 4 files that begin with "assembly" and open em all. Note: there are specific ones that you can open, you dont need em all, I got lazy trying to isolate which ones I needed exactly and just selecting em all but the 4 seems to work ok. Too lazy to update pic, but those two Assembly first pass DLL's are needed as well
    dnSpy3.png


    You should no longer get any more of the pesky compile errors.
    As I said, I am a novice at this so if you have any questions I prolly cant help, haha. Anyways, seems pretty straight forward, and so far works good for me in my tests.
     
    Last edited: Mar 21, 2019
  2. Mynar

    Mynar

    Messages:
    38
    Ratings:
    +2
    I find it kind of interesting as you almost need more of a code repository now so that people can easily make their own mods. For fun here Im gonna toss in the MAIN reason I had to get into dnSpy.
    I have seen this mentioned before, but OMFG, that person whistling, screaming or whatever during qualifying was literally gonna make me go Redrum on someone. I seriously dont know how that was left in there, maybe its just my speakers but anyways, here is my little fix.

    Annoying_sfx.png

    Under Sounds, goto the Ambience_CrowdQualifyCheer and change the value to another sfx. For me, the birds and frogs of practice are highly preferred, so that was number 2.

    Ambience_CrowdQualifyCheer = 2
    Sanity restored!!!
     
    Last edited: Mar 21, 2019
  3. Mynar

    Mynar

    Messages:
    38
    Ratings:
    +2
    As I stated I am getting better, but not super experienced at this.
    One note to add in my above steps.
    1) When you right click, then do edit method, and then you select all your references.
    I usually do this, hit cancel, then do edit method again. Now it will compile.
    2) Im sure more experienced people might be able to get away with it, but even if it seems like it works better, dont edit classes.
    3) after Im done, I save the module, and close all. Its a pain, but I reset all my references every time I do an edit. less problems for me this way.

    How to change game start date.
    As per request:
    GameStartDate.png
    As Ive outlined in the instructions above, get dnspy and load your charp.
    redcircle 1: in the search type gamestartdate
    itll find a hit which will appear directly below, click on it
    Now the redcircle 2 information will appear, click direct to the right of the date and select edit method.
    change your date, compile and your set!

    On a side note, Im not sure whatll happen if you change the start date for 1/1 when the game runs on a schedule and the season start date is set for 3/1. Heh, I guess I can try and see what happens. If you want to shift the entire event calendar, thats a whole nother thing.
     
    Last edited: Mar 30, 2019
  4. Mynar

    Mynar

    Messages:
    38
    Ratings:
    +2
    So, an interesting note on the date thing, you can set it to 1/1/12019. But youll have lilke 3 months till your first race.
    Also, because of the early date, it kinda made a pre-season for the AI and they made all sort of signings and moves. Actually could be kind of an interesting way to help randomize your new game at the start. I may play with that at another date :)
    Hehe, I would also imagine with three months of factory time and your car built, everyone cars will be improved and more reliable by the first race.

    PS
    Ok, I wasnt thinking, but the preseason thing is more about the fact that a lot of contracts now have expired. Always repercussions, so if you set it to 1/1 you get the "pre-season" and contracts expire. If you set it 3/1, it doesnt appear that those contracts "expire". Ive played with contracts and they usually expire on a set day, if you bypass that day, not sure if there is a global "check expiring contracts" routine at the end of the season, or if maybe those drivers will be stuck on the team forever? I dont know. Just some things to watch for if you change the start date :)
     
    Last edited: Mar 30, 2019
  5. Mynar

    Mynar

    Messages:
    38
    Ratings:
    +2
    Much to do about nothing. You sparked my curiosity. The game will process expired contracts on the day of or after the date of expiration, so you should be good using 1/1/2019 or 3/1/2019 as your start date.
     
  6. shortshifted78

    shortshifted78

    Messages:
    22
    Ratings:
    +4
  7. Mynar

    Mynar

    Messages:
    38
    Ratings:
    +2
    Cool, that is pretty sweet. I probably should look a little more thoroughly at what people have already done.

    Ive been working on my own little mod that I may release soon just for fun.
    Im sure some of these things Ive done have already been done, My mod plans to just focus on the vanilla game as is, with some of the things that bug me.
    Some of the things Ive done which if anyone was interested in my krap code, Id be more then happy to share
    mcar ID fix (again sure its been done on some of the bigger mods, super krap fix, but it works)
    better AI depth charts (best driver will drive best car)
    randomized sponsors offers (for a game that loves its RNG, seriously a RNG modifier works great for giving the default sponsor offers new life).
    Just finished an instant no rain version of my mod, cause Im in the middle of a really great season, and tired of my 6th race in a row with rain again!!!
    Some balancing stuff to give AI more money.

    Heh, Maybe Ill throw it up soon, just for kicks :)
     
    Last edited: Apr 8, 2019
  8. shortshifted78

    shortshifted78

    Messages:
    22
    Ratings:
    +4
    I'd like to see your solution to the mcarID fix and the randomized sponsor offers. I say post what you have figured out
     
  9. BeastyKat

    BeastyKat

    Messages:
    13
    Ratings:
    +0
    Everytime I see my nick, Im like who the F is Mynar, oh ya, its me. Never expected to really post here, but anyways, had to create a new ID.

    Bear, with me, Im verbose and I try to be thorough.

    First off, FYI, I'm a hack (not hacker), but hack :)
    But, hey we are all here just for fun.
    So, first my mCarID fix. Right now its still in proof of concept stage, but it does completely work. Ill post my code, but until I revisit this, for now, the one flaw is that it will not work if you promote a driver or hire a new driver the day of the race (doesnt include injury subs). Originally thought this would be an easy one, and it prolly is, but hey, I still got a lot to learn about this stuff.

    So the , Driver:SetCarID was the juiciest looking fix. I saw something somewhere else that made me believe that the inCarID would never equal -1 so the reserve wouldn't get set properly and their code didn't account for that. Frankly, this didn't work. But, I decided to leave it in, because my true fix pasted elsewhere, which is the same code, does work.
    public void SetCarID(int inCarID)
    {
    if (inCarID == 0 || inCarID == 1)
    {
    if (inCarID == 1)
    {
    this.mCarID = 1;
    }
    else
    {
    this.mCarID = 0;
    }
    }
    else
    {
    this.mCarID = -1;
    }

    So this technically didnt fix it, but I believe it to be the better code when it does get invoked.
    So I pasted the same code into the Driver:OnDayEnd()

    my code starts at: if (this.IsPlayersDriver())

    // Driver
    // Token: 0x06000CE1 RID: 3297 RVA: 0x000754E4 File Offset: 0x000736E4
    public void OnDayEnd()
    {
    this.personalityTraitController.UpdatePersonalityTraits();
    this.accumulatedStats.CopyImprovementRates(this.mStats);
    this.CalculateAccumulatedStatsForDay(this.accumulatedStats);
    this.AddTraitsImprovementBonus(this.accumulatedStats, PersonConstants.statIncreaseTimePerDay);
    float total = this.accumulatedStats.GetTotal();
    bool flag = total < 0f || (total > 0f && this.mStats.GetPotential() > 0f);
    if (flag)
    {
    this.mStats += this.accumulatedStats;
    this.mPotential -= total;
    this.mPotential = Mathf.Max(0f, this.mPotential);
    this.mModifiedPotential -= total;
    }
    this.mStats.UpdatePotentialWithPeakAge(this.peakAge);
    this.lastAccumulatedStats = new DriverStats(this.accumulatedStats);
    this.accumulatedStats.Clear();
    if (this.IsPlayersDriver())
    {
    int carID = this.GetCarID();
    if (carID == 0 || carID == 1)
    {
    if (carID == 1)
    {
    this.mCarID = 1;
    }
    else
    {
    this.mCarID = 0;
    }
    }
    else
    {
    this.mCarID = -1;
    }
    }
    }

    Now at the end of every day when you next/continue it sets the mCarID's properly.

    Things for me to revisit:
    1) You know you can post all you want that you need to do subs before the day of the race, and people will be like, it didnt work. And admittedly there probably is a better place to fix this, but for now, I am satisfied as there are more pressing things I want to play with :)
    2) I filtered out the AI cars, I plan on testing later to see what happens if I set their mcar ids as well? Will it perhaps effect their morale for the better if they run into car comparison checks? Maybe it will do something funny if the AI uses the mcarID in a weird different way.

    On a side note, I believe you mentioned that you did an endurance mod. Must have been a chore as a lot of endurance stuff is a little different and there are a lot of exceptions in the code to handle endurance stuff. I actually really havent played around with the endurance stuff much, so not sure if it will act differently.
     
    Last edited: Apr 8, 2019
  10. BeastyKat

    BeastyKat

    Messages:
    13
    Ratings:
    +0
    Im kinda excited about how the sponsor offer randomizer came out and particularly how I believe it can really become a great tool for helping the AI with cash flow:

    // Token: 0x060012BF RID: 4799 RVA: 0x00095FFC File Offset: 0x000941FC
    public ContractSponsor GetNewContract(Team inTeam)
    {
    ContractSponsor contractSponsor = new ContractSponsor();
    contractSponsor.sponsor = this;
    contractSponsor.team = inTeam;
    contractSponsor.SetContractState(Contract.ContractStatus.InProposalState);
    contractSponsor.offerDate = Game.instance.time.now;
    contractSponsor.offerRacesTotal = Mathf.Max(2, this.offerTimer);
    contractSponsor.offerRacesLeft = contractSponsor.offerRacesTotal;
    contractSponsor.SetOfferExpiryDate();
    float inMin;
    float inMax;
    float inMin2;
    float inMax2;
    if (inTeam.IsPlayersTeam())
    {
    inMin = -2.8f;
    inMax = 2.8f;
    inMin2 = -0.25f;
    inMax2 = 0.25f;
    }
    else
    {
    inMin = -1.8f;
    inMax = 2.8f;
    inMin2 = 0f;
    inMax2 = 0.333f;
    }
    float random = RandomUtility.GetRandom(inMin, inMax);
    int num = (int)random;
    this.contractTotalRaces += num;
    if (this.contractTotalRaces < 3)
    {
    this.contractTotalRaces = 3;
    }
    contractSponsor.contractTotalRaces = this.contractTotalRaces;
    contractSponsor.contractRacesLeft = contractSponsor.contractTotalRaces;
    float random2 = RandomUtility.GetRandom(inMin2, inMax2);
    float num2 = (float)this.totalBonusAmount * random2;
    int num3 = (int)num2;
    this.totalBonusAmount += num3;
    contractSponsor.bonusValuePerRace = this.totalBonusAmount;
    float random3 = RandomUtility.GetRandom(inMin2, inMax2);
    float num4 = (float)this.perRacePayment * random3;
    int num5 = (int)num4;
    this.perRacePayment += num5;
    contractSponsor.perRacePayment = this.perRacePayment;
    float random4 = RandomUtility.GetRandom(inMin2, inMax2);
    float num6 = (float)this.upfrontValue * random4;
    int num7 = (int)num6;
    this.upfrontValue += num7;
    contractSponsor.upfrontValue = this.upfrontValue;
    contractSponsor.SetBonusTarget();
    contractSponsor.slotSponsoringType = this.slotSponsoring;
    return contractSponsor;
    }



    Sorry for the flag bool stuff, this compiler drives me nuts sometimes with its obsessions with more and more flag bools everywhere. Scratch that, I cleaned it up, but do you know if there is anyway to prevent that?

    So the bonus for me is the player team handler so you can set the AI separately from the user and set 2x or 10x more lucrative contract offers. Here I set a +- 25 percent for the user, but a plus 0-33.3 percent for the AI. Just did this the other night (and Im trying to finish my season), but I will be experimenting with this a lot.
    But its fun as it will pretty much add a +- to the different offer categories.

    One note that Im still looking into, is that my multiplier is acting as a double multiplier. So if you look so by code, it should be increasing the by 25 percent, Im seeing 50.
    Not sure yet if the offer its pulling in is different/bigger, or Im really thinking that perhaps that there is another modifier somewhere else that effects sponsor values based on the category and division you are in. But it definitely makes for some crazy different offers that make you think a little more.
     
    Last edited: Apr 8, 2019
  11. BeastyKat

    BeastyKat

    Messages:
    13
    Ratings:
    +0
    Hmm, so today Im thinking..
    else
    {
    inMin = -1.8f;
    inMax = 2.8f;
    inMin2 = 0f;
    inMax2 = 0.333f;
    }
    is what I use to set the AI teams sponsor modifiers, this could be taken 1 step further...
    else
    {
    if (inTeam.financeController.availableFunds < 0L)
    {
    inMin = -1.8f;
    inMax = 2.8f;
    inMin2 = 1f;
    inMax2 = 1.5f;
    }
    else
    {
    if (inTeam.financeController.availableFunds < 3000000L)
    {
    inMin = -1.8f;
    inMax = 2.8f;
    inMin2 = 0f;
    inMax2 = 0.333f;
    }
    else
    {
    inMin = -1.8f;
    inMax = 2.8f;
    inMin2 = -0.1f;
    inMax2 = 0.25f;
    }
    }

    This way, you could set tiers, if the AI is broke, offer them a whopper sponsor offer...
    We'll see, just playing around :)
     
  12. shortshifted78

    shortshifted78

    Messages:
    22
    Ratings:
    +4
    That is awesome on the sponsor deal. I have a few thoughts:
    Minimum offer time should be one race, but that is all preference. I believe that offer length needs to be related to star level (or whatever the game engine calls it) so you don't get a 30 million offer for 1 race.
    So I tried adding this to my game and some weird things happened. in the lower GT series, I have an OK team I test with and I got my 18 offers. One of them was in slot 1 with just 1 star but it was for 33 races. Now admittedly, I had set the inMax to 10f, but I looked at the base offer and it was supposed to be just 4 races. It was like it multiplied instead of added based on the '+=' callout. I am also seeing the offer amounts being greater than possible based on the percentage limits I am setting. I think that somehow 'perRaceCostsxxx' under gameStatsConstants is getting involved.

    I made some tweaks and am trying this:
    Code:
    contractSponsor.SetOfferExpiryDate();
            float inMin;
            float inMax;
            float inMin2;
            float inMax2;
            if (inTeam.IsPlayersTeam())
            {
                inMin = -1f;
                inMax = 1f;
                inMin2 = -0.10f;
                inMax2 = 0.10f;
            }
            else
            {
                inMin = -1f;
                inMax = 1f;
                inMin2 = -0.01f;
                inMax2 = 0.2f;
            }
            int num = (int)RandomUtility.GetRandom(inMin, inMax);
            this.contractTotalRaces += num;
            if (this.contractTotalRaces < 1)
            {
                this.contractTotalRaces = 1;
            }
            contractSponsor.contractTotalRaces = this.contractTotalRaces;
            contractSponsor.contractRacesLeft = contractSponsor.contractTotalRaces;
            float random = RandomUtility.GetRandom(inMin2, inMax2);
            int num2 = (int)((float)this.totalBonusAmount * random);
            this.totalBonusAmount += num2;
            contractSponsor.bonusValuePerRace = this.totalBonusAmount;
            int num3 = (int)((float)this.perRacePayment * random);
            this.perRacePayment += num3;
            contractSponsor.perRacePayment = this.perRacePayment;
            int num4 = (int)((float)this.upfrontValue * random);
            this.upfrontValue += num4; 
    [\code]
     
  13. shortshifted78

    shortshifted78

    Messages:
    22
    Ratings:
    +4
    the above code led to this
    https://www.flickr.com/gp/169651413@N04/Y93Xsi
    Which ended up creating a per race income of over 4 million. So I think I still need to tweak slightly

    The next thing I would like to see done with sponsors is working with the categories, and limiting offers from say automotive or oil or fuel or alcohol sponsors since in real life multiple car manufacturers are not going to want to go on a single race car, nor would multiple fuel or oil companies.
     
  14. BeastyKat

    BeastyKat

    Messages:
    13
    Ratings:
    +0
    Strange on the day having so many days added, I will definitely need to investigate more as to the other variables coming into play here.

    When I look at that Sponsor class there actually are preset categories and the routine for grabbing a sponsor offer, i wouldnt think it would be too hard to have it scan for existing offers and grab a different offer if there is a category clash...
     
  15. Mattmoen

    Mattmoen

    Messages:
    2
    Ratings:
    +0
    Errr... Is here somebody has been edit front end file? I really want to know how you do that. Thanks
     
  16. shortshifted78

    shortshifted78

    Messages:
    22
    Ratings:
    +4
  17. jimpanse3000

    jimpanse3000

    Messages:
    1
    Ratings:
    +0
    Sry I'm a few months late on this, but i only discovered this now. Being a noob to editing dlls myself, i thought maybe you had an idea what I'm doing wrong.

    Using the 1993 MOD i need the gamestartdate to be set to that year so that the conracts don't expire once i start a new carreer.
    There is a csharp.dll included in the 1993 MOD that would probably do this. But i don't want to replace the csharp.dll i already use, since it is the one from the no-macro-MOD and i want to keep its options. So i wanted to edit the start date in the csharp-dll of the no-macro-MOD in order to sort of combine the two mods.
    I followed your instructions to edit the entry for the start date, but unfortunately i can't manage to compile when I'm done. I always get multiple error massages, telling me f.e. [The type "GameTimer" already contains a definition for "speedMultipliers".]. I didn't touch this entry at all and the game worked fine with this supposed error in the dll-file.
    I selected all the references, tried the method with the canceling and compiling afterwards, but nothing changes. Now I'm lost, hoping for help ;-)
     
  18. shortshifted78

    shortshifted78

    Messages:
    22
    Ratings:
    +4
    Are you using a version of dnspy newer than 6.01?
     
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.