Any elegant solution to trigger something when a building gets destroyed?

Started by pawnstorm, April 29, 2014, 12:14:24 AM

Previous topic - Next topic

pawnstorm

Perhaps it helps if I elaborate on what I'm trying to do. I'm working on an expansion of my Battle Formations mod, which adds a structure called an automaton. The main function of the structure is to act as sort of an automated threat response system. When raiders or psychotic animals show up, it will automagically send out your colonists to deal with the threat. I got that part working, mostly, though it still needs some polishing. I also want to automatically mark animals for hunting when running low on meat, shouldn't be too hard either.

The thing I can't see an elegant solution for is I also want it to automatically put down new blueprints when things get destroyed. Maybe it's just not feasible but I figured maybe someone more clever than me can come up with something I hadn't thought about ;).

Haplo

It wouldn't be easy to make something like that.
You'll have to find all your buildings and save their positions and defs.
Next you'll watch out for their health. If it falls under a threshold you have to mark it as possible damaged. If it then is suddenly not there any longer you can build the blueprint according to the saved Def.

On another note: I would make automatisms for the fighting an optional thing. Not a part of the main release, as it takes most of the fun out of the game, if it does everything automatically for you..
Just my thoughts...

WorldOfIllusion

you could add code to the Destroy or DeSpawn methods in your custom class. Unsure what the process for adding a new blueprint by code would be though (although when you work that out it should be as simple as adding it to one of the aforementioned methods).
Artistically challenged modder seeking artistically talented texturer's help. Please, please, PM me :)

mrofa

You could try to make a zone or a marker like thingy that will allow player to select which building will be checked for auto response.
All i do is clutter all around.

pawnstorm

Quote from: Haplo on April 29, 2014, 01:04:32 AM
It wouldn't be easy to make something like that.
You'll have to find all your buildings and save their positions and defs.
Next you'll watch out for their health. If it falls under a threshold you have to mark it as possible damaged. If it then is suddenly not there any longer you can build the blueprint according to the saved Def.
Yeah, that was the only solution I could come up with too. It seems rather inefficient and taxing on the system, if this is the only way to do it I think I'm going to wait for alpha 4 and see if it offers a more elegant way.
Quote from: Haplo on April 29, 2014, 01:04:32 AM
On another note: I would make automatisms for the fighting an optional thing. Not a part of the main release, as it takes most of the fun out of the game, if it does everything automatically for you..
Just my thoughts...
I'm not going to integrate it into my Battle Formations mod, it'll be a separate expansion. The automaton will probably also have a really high research cost and draw a lot of power, to encourage people to only use it when their base is already well established.

pawnstorm

Quote from: WorldOfIllusion on April 29, 2014, 01:10:17 AM
you could add code to the Destroy or DeSpawn methods in your custom class. Unsure what the process for adding a new blueprint by code would be though (although when you work that out it should be as simple as adding it to one of the aforementioned methods).
The problem with that is a lot of different buildings and structures use different building classes, so I'd have to extend them all and it wouldn't be compatible with any mods.
Quote from: mrofa on April 29, 2014, 01:13:22 AM
You could try to make a zone or a marker like thingy that will allow player to select which building will be checked for auto response.
I think in practical use, people will just drag the zone over their whole base so it doesn't really remove any of the complexity.

mrofa

Yes but i mainly meant that for what haplo writen, this would help your code to identify position,hp and defs to monitor them, you could use the storage code for that, same as it couts resources defs to the resource bar.
All i do is clutter all around.

pawnstorm

I think I may have come up with an elegant solution, actually. Things can have attachments, which are of the AttachableThing class. When a Thing gets destroyed, it'll also call Destroy() on all of its attachments. So if I create my own attachable thing, I can override the Destroy() method and I'll know when the building gets destroyed :).

Architect

Can you give an example of this attachment thing? I'm not sure I understand your meaning of what it is.
Check out BetterPower+ and all its derivatives by clicking the picture below.

It adds many new methods of power generation and uses for it, as well as other things such as incidents.


pawnstorm

Quote from: Architect on April 29, 2014, 05:43:45 AM
Can you give an example of this attachment thing? I'm not sure I understand your meaning of what it is.
Right now, I think it's only used for fire. Objects which inherit from the Thing class have a List<AttachableThing> attachments property. An AttachableThing is basically just a Thing you can attach to another Thing. It also knows what it's attached to, and it gets destroyed when its parent gets destroyed so it's perfect for my scenario! :)

pawnstorm

ThingComp seems to be even more suitable. It even allows me to add it to things in the xml files, you can find out marvelous things if you run grep -ir "Class>" from the Mods/Core directory :).

Edit: This is actually pretty powerful stuff... you can basically add your own custom code to the spawning or destruction of any ThingWithComponents derived object, aswell as tickers, variables, custom buttons, overlay graphics, etc.

Sion

Quote from: Haplo on April 29, 2014, 01:04:32 AM
It wouldn't be easy to make something like that.
You'll have to find all your buildings and save their positions and defs.
Next you'll watch out for their health. If it falls under a threshold you have to mark it as possible damaged. If it then is suddenly not there any longer you can build the blueprint according to the saved Def.
...

Wouldn't it be possible to only monitor when things take damage? without needing to monitor everything on the map?
Something like: when something first receives any damage it saves and monitors the structure, if it gets up to 100% health again it can simply be forgotten again, if it goes to 0% it is replaced.

Please note that I have no knowledge about the programing language used to mod RimWorld, but I know some things about programing, unfortunately only small fragments.

Pseudo code:

SomeFunctionToInterseptDamageToThings() //Destroy or DeSpawn methods?

if(item.Damaged()) then
   MonitorList.Add(item)
   if(item.Health() <= 0) then
      item.Replace()
   EndIf
   if(item.Health() >= item.MaxHealth()) then
      MonitorList.Remove(item)
   EndIf
EndIf

So many ideas... so little time...
Silence is the worst answer.

pawnstorm

Quote from: Sion on April 29, 2014, 02:23:19 PM
SomeFunctionToInterseptDamageToThings() //Destroy or DeSpawn methods?
That's the problem, there's no method to intercept damage to things, but I think I can solve it by just slapping a custom component (ThingComp) on things and then when it gets destroyed, I'll know the thing I attached it to got destroyed too.

Tynan

This is actually well-supported. Write a custom ThingComp class and make your XML reference it in the def.

For example, here is the CompGlower code:


using UnityEngine;
using System.Collections;




public class CompGlower : ThingComp
{
//Properties
private bool glowOnInt = false;
public bool Lit
{
get
{
return glowOnInt;
}
set
{
if( glowOnInt == value )
return;

glowOnInt = value;

if( value == false  )
{
//turning off
Find.MapDrawer.MapChanged(parent.Position, MapChangeType.Things); //For my glow plane
Find.GlowGrid.DeRegisterGlower(this);
}
else
{
//turning on
Find.MapDrawer.MapChanged(parent.Position, MapChangeType.Things); //For my glow plane
Find.GlowGrid.RegisterGlower(this);
}
}
}
public int RadiusIntCeiling
{
get
{
return (int)System.Math.Ceiling(def.glowRadius);
}
}


public override void CompSpawnSetup()
{
//Essential in rebuilding the glow map after loading
if( Lit )
Find.GlowGrid.RegisterGlower(this);
}


public override void CompExposeData()
{
Scribe_Values.LookValue( ref glowOnInt, "glowOn");
}


public override void CompDestroy()
{
base.CompDestroy();

Lit = false;
}
}


Note that it catches the destruction of the parent Thing using CompDestroy and unlights itself. In your case, you could issue some sort of AI signal from here.
Tynan Sylvester - @TynanSylvester - Tynan's Blog