Few features I'd like to know how to make

Started by TomaszA2, October 12, 2019, 04:02:48 PM

Previous topic - Next topic

TomaszA2

I was making just for myself some modded items and buildings and some ideas needed more information than I posess.

The first thing that I wanted to ask for is if it is possible to make item stat change triggered on it's user death with xml, because as I am able to do that with C# I would like to know first whether easier way exists or not.

Second problem: I've been trying to make weapon that damages it's user with each shot while also the projectile goes and do damage to enemy as well. It looked to me like there are only ways to damage your target with weapon, so I am asking here. Can I do that with usage of xml(which I think I should be able) or I need to go for C#?

I wanted one building to produce massive heat as it's downside, so, is that possible to make it less efficient(energy storing/battery) while it's outside? I've been trying to make it immediately exploding if rain touches it but as I saw I couldn't make explosion faster than it is on normal batteries or other machines in rain.

And the last one. Can I somehow limit spawn/creation of an item to one per save or one exist at a time on that world square/colony?

That's all for now. I'll appreciate any help or tips.

K

Generally, you're describing complex behaviors that are probably beyond what can be accomplished with solely XML. The best way to approach the problems you've described is likely a custom Comp class that you can apply to the things you're creating (weapons, buildings, ect), which you would need to write in C#.

As for limiting the spawning and creation of items, that could be more complicated. Since restrictions like that don't exist in the base game as far as I know, you'd likely have to use Harmony to try to enforce such a condition. There might be a lot smarter and less brute force way than that, though.


LWM

One approach for the one-per-world object would be to create a derived Thing class that on spawning, if your mystic object doesn't exist, switches its thingDef to the mystic item, but if there is already one, switches the thingDef to, I don't know, dogPoop or whatever. (regularNonMagicSword?)(cheapPlasticImitationAmuletOfYendor?) - and then spawns the appropriate object.  There may be much better approaches, but I think this one would work and doesn't require Harmony.  It would definitely require C# ;)

--LWM

TomaszA2

#3
Okay, as I am not familiar with XML and C#(honestly the only thing I can freely write in is C++) I have a few questions.

The thing I am working on as first is the sword that gets it's stats increased every time it's user dies. (optionaly in battle, or stats increasing only when character stats fits some conditions)
The first problem is that I am not sure how to merge XML and C# in the way that would allow me to write basic strength and multiplier/added stat in xml and let it modify item statistic through C#. Even if it wouldn't be hard, I am not sure how to manage item properties through C#.

It would be helpful to have some mod written with XML and C# to make sword/melee weapon that has stats modified in any way by C# script/program/dll, but I haven't heard about any mod like that or just I was searching wrong for it.

About just the sword idea, I have no name for it yet, also I know it may be easy to exploit(killing manualy your own people with it equipped) but still I think it may be awesome for making stories. (The Legendary Sword that allows you to revenge all previous topclass knights that wielded it before within their own power combined and provide safety to your land.)
Anyway I don't think about giving it any overpowered boost. Small boost that would be noticeable after many wielders defeated in battle.
Question about only one exsisting iteration of an item(to avoid making more of it) was also about this one idea. While still it will have huge cost in resources it may be easily reproduced in later phases of game.
Even though it is only for me (and maybe my friends) I don't want to let myself overuse it in any way.
In my actual one-death save I have one knight and all others with ranged weapon, and that knight has Uranium sword of the latest warrior that had been on his place before. That's why I came up with the idea of this. And I wouldn't play this save anymore until I'll make this idea real.

It was so much about just the idea, shortly said it's just for story purposes.
I was always slowly catching up C# and rimworld XML so I think it isn't the last question here.

Edit. As I think about it, I have to know how to trigger something in moment of moving weapon to the ground when character collapse and check if this character is dead. I'm starting to think it's beyond my searching capabilities.

Red192

As far i know rimworld uses xml just for read fields and data, not for describe any coded behavior.

Unless you are not activating/disattivating boolean, add or remove fields, increase or decrease values, any other kind of code will be ignored.

In other words: since the behavior you described is not used by any other weapon defs in the game should not be possibile to achieve what you are looking for by just modifying some xml code.

I'm have just begin to work on a mod and it's the first code project EVER, even little things are quite challenging to me (but quite fun i would say). However I think your idea could be done by a beginner thou, you should try to read the wiki a for setting up the C# workplace and begin to explore the code, if you want you can also follow the plagueGun tutorial, but i think you can also start right away

TomaszA2

I've found VerbProperties.meleeDamageBaseAmount. (probably it's something else than I think) I am not sure(read: I don't know) how to apply change to this one item object. (sword that is already made and exist in game)
Also as I said before I have no idea how to check if that exact colonist is dead already. (also how to get his ID(?) when he is equipping it for the first time to check later after item is dropped if it's owner has died)

For now I have only this fragment.

namespace The_PlaceholderName_Sword
{
public class BoostOnDeath
{
//public bool isEquipped = false;
//public string owner = "";
BoostOnDeath()
{
if()
{

}
}


}
}

LWM

Quote from: TomaszA2 on October 13, 2019, 03:25:29 PM
Okay, as I am not familiar with XML and C#(honestly the only thing I can freely write in is C++) I have a few questions.
I cannot recommend the wiki over at http://rimworldwiki.com/ enough - it has a lot of helpful things that answer a lot of questions.  Also, I cannot recommend asking people here, as you are doing - we often know where to find those answers ;)

So a couple of thoughts:

One approach would be to use a ThingComp, which is easy to add to ANY given weapon.  Another approach - possibly better, given the unique properties of the proposed item - would be to make a derived C# class from whatever class makes weapons.  When a pawn uses it in battle, you can probably find a way to trigger who the pawn who is using it is.  Then whenever the item gets spawned you can check if that user is dead.  If not, reset the user etc.

....right.  So, RimWorld.

First, in general, in RimWorld there are generally two matching sets of things: XML and C# code - these correspond in large part 1:1.  This is something I'm quietly think about as I toss ideas out, because ThingComps(tied to in-game objects) can have information CompProperties(tied to XML) don't have...but I don't know which one is used to calculate damage.

Spawning.  If a pawn is holding the Ultimate Rod of Vengeance, it hasn't been "spawned."  (I think this is how it goes for weapons.)  If she is using it in battle and dies (and drops it), or is told to put it down from the gear tab, or is just carrying it to a stockpile and puts it down, or anything else that puts it on the map, it "spawns."  So that, I think, will be a place to check if the user has been killed (altho for all I know when a pawn dies, something tells the weapon so - I have mod experience with hauling, not weapons ;) ).

If I might make suggestions:

Consider making Mod Settings that allow you to change how powerful the item gets when its user dies (if you play on Baby settings, it won't happen very often; if you play on MurderSprees, it happens often) so everyone can play with it how they choose.  They are useful and it's easy enough to cut and paste from a mod available on github.

Decide if you want only one type of weapon to be available.  If not, make a comp - heck, a comp might be an easy way to enforce only one instance of the weapon.  A comp does have the disadvantage that it comes in two parts: the CompProperties for the XML and the ThingComp for the object in-game.

Start modding by making a weapon that gets a flat change to damage based on the mod settings.  It's an easy change and will get you used to RimWorld...

Go from there :)

I hope that helps.

I like the weapon idea - it sounds like it'd be fun, and I can see plenty of people wanting it.  Good luck!  You got this.

--LWM

TomaszA2

I'd never expect dropping item to be ,,spawned". This advice is probably the best I could have got here, thank you. Also your idea of making a weapon with flat bonus based on settings is really nice. Simple (how didn't I think about it before...), fast, giving me some advice on how-to in final version and reusable.(This code can be easily modified to be a base for whole thing)

I was making few things in C# for rimworld before I stopped playing for around half of the year or longer last time. These mods had their own menu section in mod-settings. It wouldn't be any problem for me so I can almost immediately try myself in making that magical sword code.

I have read many tutorials already(long time ago as in few latest days) and wouldn't ask here if they helped me in bringing it to the end. (or even start) It came out with your latest message it was indeed great idea to ask here. Just one thing that I didn't know before doing so is that the item respawns itself with every drop of it.

I think I know everything I need except:
- how exactly am I supposed to change properties of that exact existing in game object in playing time,
- how to save this between loadings of game(or is it rimworld saves itself in the way that just ,,continues" the game state so I wouldn't need to think about it),
- that if there can be two persons with the same name(then if one is dead, item would get bonus just after first creation/spawn, probability is like none but some peoples are using character editor mod in colonist choosing menu, still nearly nobody makes two characters the same but still bug is a bug)
These things are probably something that I'll figure out later without any problem or help needed.

I am going to work now on it for some time, the next time you'll see me I'll probably have it done or got some new problem. For now I am satisfied with all the answers and tips I got there. Thanks to everyone.

LWM

Quote from: TomaszA2 on October 15, 2019, 01:12:05 PM
I have read many tutorials already(long time ago as in few latest days) and wouldn't ask here if they helped me in bringing it to the end. (or even start) It came out with your latest message it was indeed great idea to ask here. Just one thing that I didn't know before doing so is that the item respawns itself with every drop of it.
I have done a little cleaning up of the wiki, and Mehni has done a LOT - there's a lot of useful information there now....for certain specific bits of information ;)  So it has its place in your toolbox.

Quote
I think I know everything I need except:
- how exactly am I supposed to change properties of that exact existing in game object in playing time,

Here is how I would handle this: I would look through the code to try and figure out where damage happens and then track where those numbers come from.  Other good options include asking here  ::)  'Cause there will be people here who know.  You might have to mess with ...StatDefs?  You'll figure it out :)

(Okay, I thought that was funny advice, but I've got a cold....)

Quote
- how to save this between loadings of game(or is it rimworld saves itself in the way that just ,,continues" the game state so I wouldn't need to think about it),

Whatever you implement (Thing-derived class, ThingComp, whatever) will have some variant of a function called "ExposeData" - that's what handles saving/loading things.

Quote
- that if there can be two persons with the same name(then if one is dead, item would get bonus just after first creation/spawn, probability is like none but some peoples are using character editor mod in colonist choosing
menu, still nearly nobody makes two characters the same but still bug is a bug)

Every "Thing" in the game (including people) has a unique ID.  I think it's ThingID?  Alternately, everything has a HashCode; you could use that.  If people somehow make two characters with the same ThingID/HashCode, they deserve to break things.

Have fun, look forward to it, glad it helped!

--LWM

TomaszA2

It wasn't like I wanted to know and didn't try to search through game code, I had already few hours spent on searching for it.(I'm very bad in searching through this)
I just needed some key word to search for in IlSpy.

For now I've finished that mod settings menu and I am searching for things I need with IlSpy.(first thing I tried to search is about that whole spawning, after that I'll try looking for stats with your advice)

LWM

Quote from: TomaszA2 on October 15, 2019, 03:22:06 PM
It wasn't like I wanted to know and didn't try to search through game code, I had already few hours spent on searching for it.(I'm very bad in searching through this)
I just needed some key word to search for in IlSpy.

Oh don't ever feel bad for asking ppl here for advice - there are some really helpful people who have really useful bits of information or hints that can take a long time to suss out oneself!

--LWM

TomaszA2

#11

I am able to change ,,power" (flat damage of attack types?) but it yet gives me many errors.
public  class OmniSwordClass : ThingDef
{
public OmniSwordClass()
{

}
public void changeAttack(Tool test)
{
test.power = 200f;
}
public override void PostLoad()
{
tools.ForEach( changeAttack );
}
}


I am using this OmniSword name just as placeholder. I'm not going to name it before I would have finished the code.
Why are these ,,tools" having null ID and why is it talking about ID duplicate? (errors at the beggining of post)

Edit:
Also item icon disappeared.

.xml file is attached to the post, but I don't think it's something caused by it, I haven't touched  it for few hours. (but had open so maybe I did something accidentaly)

LWM

You didn't do base.PostLoad(); the tools have no ids yet.

TomaszA2

namespace The_Legendary_Omni_Sword
{
public class CompBoostOnDeath : ThingComp
{
List<Tool> toolsList = new List<Tool>();
/*public CompBoostOnDeath()
{
} Without this rimworld log error is saying ,,default constructor cannot be found" but with it just doesn't change any power stat
*/
public CompBoostOnDeath(ref List<Tool> tool)
{
toolsList = tool;
}
public void changeAttack(Tool test)
{
test.power = 200f;
}
public override void PostSpawnSetup(bool respawningAfterLoad)
{

Log.Error("teteteeettt", false);
toolsList.ForEach( changeAttack );
}

}
public  class OmniSwordClass : ThingDef
{
public OmniSwordClass()
{

}
public override void PostLoad()
{
base.PostLoad();


CompBoostOnDeath tempThingComp = new CompBoostOnDeath(ref tools);

CompProperties tempCompProperties = new CompProperties();
tempCompProperties.compClass = typeof(CompBoostOnDeath);

comps.Add(tempCompProperties);
}
}
}


I've been trying to make stat change proceeded in comp class, because this is where PostSpawnSetup is declared so it's also the only place where I can use it.

Even if it's compiling correctly it throws error to me inside of the game.


I know it should have used constructor with one argument as it is what I did in the code(or at least I think I did) but it looks like it had just ignored argument and looked for basic constructor.

About your last advice, that was the next thing I wouldn't think about if someone hadn't told me about.

LWM

#14
Oh, come at it from the other direction?

In the ThingComp's postload...Initialize(), you can directly access the thingdef:

this.parent.def.tools etc.