Author Topic: A couple questions for Keith  (Read 12312 times)

Offline BadgerBadger

  • Arcen Volunteer
  • Hero Member Mark III
  • *****
  • Posts: 1,229
  • BadgerBadgerBadgerBadger
A couple questions for Keith
« on: July 11, 2017, 11:29:42 pm »
Hey Keith, a few quick ones for you.

Are there any obvious hooks that exist for "Have the AI gain a particular type of unit every X AIP", or "Have an AI or a Special Faction gain a particular type of unit every Y minutes"?

Also, is there any mechanism for a unit to know how long it has been alive?

I feel like there are a number of cool opportunities for "Every so often, have something interesting spawn on the map", followed by "If you've left the interesting unit alone for too long, have it do something really nasty" in modding land.

Offline keith.lamothe

  • Arcen Games Staff
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 19,505
Re: A couple questions for Keith
« Reply #1 on: July 12, 2017, 08:05:57 am »
Are there any obvious hooks that exist for "Have the AI gain a particular type of unit every X AIP"
There's CheckForSpendingUnlockPoints for unlocking types that it can then build normally; that's based on "what's the highest the effective AIP has ever been?" so if it keeps going back down and then up without reaching a new "high water mark" the AI doesn't get new stuff.

Or do you mean just spawning a new ship somewhere? There's no obvious hook there at the moment on the AI itself, but you could add a Conduct and put whatever such logic in that Conduct's DoPerSimStepLogic method. You could check "if(World_AIW2.Instance.IsFirstFrameOfSecond && World_AIW2.Instance.GameSecond % 60 == 0)" for doing something once every minute, etc, and you can spawn new units using GameEntity.CreateNew (example usage in BuildPattern_BasicTurretry).

I'll see about adding an external DoPerSimStepLogic for AI types, so you don't have to rely on the Conduct being there and switching on the AI type, etc.

Quote
or "Have an AI or a Special Faction gain a particular type of unit every Y minutes"?
See above for the AI. For a Special Faction they have no concept of "unlocks" but if you mean just spawning a new ship somewhere there's a DoPerSimStepLogic on the special faction controller (SpecialFaction_DysonSphere is a good example; it's not spawning stuff there but it could).

Quote
Also, is there any mechanism for a unit to know how long it has been alive?
Not exactly, entity has SecondsSinceEnteringThisPlanet which would work for units that don't go through wormholes. I'll see about adding a SecondsSinceIWasCreated.
Have ideas or bug reports for one of our games? Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline BadgerBadger

  • Arcen Volunteer
  • Hero Member Mark III
  • *****
  • Posts: 1,229
  • BadgerBadgerBadgerBadger
Re: A couple questions for Keith
« Reply #2 on: July 12, 2017, 10:02:13 am »
So let me check and see if I understand how BasicTurretry finds its turrets. It gets a GameEntity BuildingEntity
object passed in, then it looks at all the available Build Menus, and foreach build menu all of the objects in it to find things that look like turrets.
I'm assuming the various BuildMenus are things like FleetShips_I_Thru_IV, ConstUnits and Turrets, as defined in KDL_BuildMenus.xml.

So if I wanted to copy this approach, I might define a new Badger_BuildMenu.xml, with a "MaliciousMonsters" build menu. It looks like BuildMenu has a Name, so I would iterate over the BuildMenus till I found one whose Name was "MaliciousMonsters". Then I would iterate over that list and either pick one by name (if GameEntityTypeData.Name == "FirstMonster") or pick one at random and then call GameEntity.CreateNew, passing in my GameEntityTypeData for the chosen monster (along with the other required fields).

That leaves open the question of where I get the BuildingEntity object into my PerSimStepLogic function; it looks like its passed in as an argument. Is there a global I can talk to?

Alternatively, I notice in MapGeneration.cs you call
                        GameEntityTypeData warpGateData = GameEntityTypeDataTable.Instance.GetRandomRowWithTag( Context, "WarpGate" );
and then pass that GameEntityTypeData to CreateNew

Could I use an approach like that to find a Monster to spawn?
« Last Edit: July 12, 2017, 10:07:14 am by BadgerBadger »

Offline keith.lamothe

  • Arcen Games Staff
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 19,505
Re: A couple questions for Keith
« Reply #3 on: July 12, 2017, 11:23:32 am »
Oh, yea, I didn't mean to use the whole of how basic-turretry works, just saying that's a good example of a GameEntity.Create() call being used during the game (as opposed to mapgen). You don't need anything other than that Create() call as long as you have the parameters for it, though depending on what you want that new entity to _do_ you may need to add more logic after that.

GetRandomRowWithTag() is probably your best bet for getting one from a group of entity types, without actually hardcoding the entity internal name. You can use the internal name if that makes sense, by GetRowByName() or something like that.
Have ideas or bug reports for one of our games? Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline BadgerBadger

  • Arcen Volunteer
  • Hero Member Mark III
  • *****
  • Posts: 1,229
  • BadgerBadgerBadgerBadger
Re: A couple questions for Keith
« Reply #4 on: July 14, 2017, 01:35:01 am »
So BasicTurretry takes a CombatSide as an argument. GameEntity.Create() takes a WorldSide. I feel like you can map from a WorldSide to a CombatSide, but I'm not sure how to go the other way.....

Offline keith.lamothe

  • Arcen Games Staff
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 19,505
Re: A couple questions for Keith
« Reply #5 on: July 14, 2017, 10:13:45 am »
So BasicTurretry takes a CombatSide as an argument. GameEntity.Create() takes a WorldSide.
The signature is:
Code: [Select]
public static GameEntity CreateNew( CombatSide Side, GameEntityTypeData TypeData, ArcenPoint StartingLocation, ArcenSimContext Context );
Quote
I feel like you can map from a WorldSide to a CombatSide, but I'm not sure how to go the other way.....
Code: [Select]
WorldSide worldSide = combatSide.WorldSide;
Code: [Select]
CombatSide combatSide = planet.Combat.GetSideForWorldSide( worldSide );
CombatSide is just the association table between WorldSide and Planet (CombatEncounter, specifically, but that's just a sub object of Planet), so each CombatEncounter object has one CombatSide object for each WorldSide object in the game.

In other words a CombatSide contains all the information about a specific WorldSide that is specific to that planet. Notably, all the units that WorldSide has on that Planet.
Have ideas or bug reports for one of our games? Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline BadgerBadger

  • Arcen Volunteer
  • Hero Member Mark III
  • *****
  • Posts: 1,229
  • BadgerBadgerBadgerBadger
Re: A couple questions for Keith
« Reply #6 on: July 14, 2017, 02:51:50 pm »
Great! I have now made the Dyson Sphere spawn bombers and random golems every 5 seconds. The Dyson Sphere just conquered the galaxy.

Also, I observe a difference between the documented Dyson Sphere behaviour in the wiki and what's coded.
In the code, here is what happens:
AI Owns planet:        Dyson Sphere hates AI, likes players <=== this should be what happens when Noone owns
Player owns planet:   Dyson Sphere hates players, likes AI
Noone owns planet:   Dyson Sphere hates everyone.         <=== this should be what happens when AI owns

Thoughts?

Offline keith.lamothe

  • Arcen Games Staff
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 19,505
Re: A couple questions for Keith
« Reply #7 on: July 14, 2017, 03:48:07 pm »
Fixed for 0.503, thanks :)

Edit: and congrats on conquering the galaxy with a golem-spawning Dyson :)
Have ideas or bug reports for one of our games? Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline BadgerBadger

  • Arcen Volunteer
  • Hero Member Mark III
  • *****
  • Posts: 1,229
  • BadgerBadgerBadgerBadger
Re: A couple questions for Keith
« Reply #8 on: July 15, 2017, 05:45:07 pm »
Another question for you! Is there an equivalent to GameEntity.CreateNew, but which destroys the unit?

Offline keith.lamothe

  • Arcen Games Staff
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 19,505
Re: A couple questions for Keith
« Reply #9 on: July 15, 2017, 09:37:36 pm »
Another question for you! Is there an equivalent to GameEntity.CreateNew, but which destroys the unit?
You probably want GameEntity.Die()

It's not an equivalent in that it doesn't actually remove the unit from the game instantaneously, it just puts it in the destroyed state for cleanup in the normal way.
Have ideas or bug reports for one of our games? Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline BadgerBadger

  • Arcen Volunteer
  • Hero Member Mark III
  • *****
  • Posts: 1,229
  • BadgerBadgerBadgerBadger
Re: A couple questions for Keith
« Reply #10 on: July 17, 2017, 01:34:09 am »
For Factions, is there a GetWorldSideByName() function? I'm trying to get specific WorldSides (for example, I want to have a faction that hunts the devourer golem. So I need the WorldSide of the Devourer so I can target it, but at the moment the only way I know how to do that is to iterate over all the WorldSides until I find one whos SpecialFactionData.Name == "targetName".

Offline Draco18s

  • Resident Velociraptor
  • Core Member Mark V
  • *****
  • Posts: 4,251
Re: A couple questions for Keith
« Reply #11 on: July 17, 2017, 12:04:11 pm »
An in-built function would probably just do that anyway.

Offline BadgerBadger

  • Arcen Volunteer
  • Hero Member Mark III
  • *****
  • Posts: 1,229
  • BadgerBadgerBadgerBadger
Re: A couple questions for Keith
« Reply #12 on: August 19, 2017, 12:36:23 pm »
It's my understanding that you shouldn't try to persist List<GameEntity> across different SimSteps. This leads to a bit of difficulty if I want to coordinate ships for long periods of times. Lets say I want to build several fleets on different planets, then send them out in a coordinate fashion to strike the Ark. I'm having trouble trying to figure out an efficient way of doing this that doesn't involve building a state machine in my Special Faction. But if I could put some sort of tag on GameEntities then that would simplify things tremendously. I'd be able to do things like "In the LongRangePlanning, find all the Entities tagged with 'Fleet 1' and do something, then find all the Entities tagged 'Fleet 2' and do something else".

Is there a way I can get some sort of extra value added to a GameEntity (public int modderField1 that starts at 0 when an entity is created) or something?
« Last Edit: August 20, 2017, 12:07:44 pm by BadgerBadger »