Author Topic: OP2 Scenario Project for C#  (Read 1631 times)

Offline Vagabond

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 842
Re: OP2 Scenario Project for C#
« Reply #50 on: March 31, 2019, 07:28:42 AM »
Haven't tested yet, but have you tried from Outpost2DLL:

Code: [Select]
void SetFactoryCargo(int bay, map_id unitType, map_id cargoOrWeaponType);	// [StructureFactory, Spaceport]  [Note: If items is an SULV, RLV, or EMP Missile, it is placed on the launch pad instead of in the bay]

Might be able to use unitType SULV and cargoType of spaceship part. I can update the comment based on your results.

---

Just a speculation, but someone may have to go into UnitInfo or UnitEx on HFL to get building status and figure out which unknown it is? You might want to check IUnit-HFL to see if it has a building status field (I have never used it). Since the AI cheats, I guess I've never worried about it.

-Brett

Offline TechCor

  • Newbie
  • *
  • Posts: 34
Re: OP2 Scenario Project for C#
« Reply #51 on: March 31, 2019, 08:57:34 AM »
It doesn't work. It will place an empty SULV on the pad.

I'll try dumping out the OP2Unit struct to a log file, disable a structure, and dump it again to see what changed.

EDIT:

This wasn't as easy as I was hoping it would be:

Active:
unknown5 = -2144927203
flags = 8449037
unknown7 = -2144927203
timerStickyfoam = 0

Disabled:
unknown5 = 2556445
flags = 8440844
unknown7 = 2556445
timerStickyfoam = 7

---
The log was printing continuously (no way to detect keypress AFAIK).
timerStickyfoam changed a few times in there.

timerStickyfoam started at 0.
Then it went to 519.
Then it went to 263.
Then the other values changed (I assume from becoming disabled) and it went to 7.

I'm thinking it might represent the structure animation state, but I am just speculating.



Decided to assume it has something to do with the flags and ran multiple tests for each disable type.

00000000 10000000 11101100 00001101 - Enabled
00000000 10000000 11001100 00001100 - Power
00000000 10000000 00101100 00001100 - Tubes
00000000 10000000 00001100 00001100 - Idle
00000000 10000000 01101100 00001100 - Scientists
00000000 10000000 00101100 00001100 - Workers and scientists
00000000 10000100 00101100 00001100 - Infected

It looks to me:

byte 2:
bit 6 = Is infected

byte 3:
bit 1 = Has scientists?
bit 2 = Has workers
bit 3 = Has power

byte 4:
bit 8 = Lights (Already defined in file)

There doesn't appear to be a "Connected to CC" flag which is very confusing. I checked for other differences between "disabled CC" and "disabled workers" and found none. They are considered identical in OP2Unit.



Tested spaceport with empty SULV and one with Phoenix module loaded. The cargo is very clearly placed into "unknown14", as the value gets set from 0 to 99 (Phoenix module map_id).
« Last Edit: March 31, 2019, 06:59:28 PM by TechCor »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4740
Re: OP2 Scenario Project for C#
« Reply #52 on: March 31, 2019, 08:33:47 PM »
Good question about loading rockets. I'm not actually sure. I'm not sure if an AI ever does that. I only remember the AI launching EMP Missiles, where there is a special function for in TethysGame. In terms of direct Unit control, the only exported methods for manipulating specific units seems to be:
Code: [Select]
	// Specific Building
map_id GetObjectOnPad() const; // [Spaceport]
void DoLaunch(int destPixelX, int destPixelY, int bForceEnable); // [Spaceport]
void PutInGarage(int bayIndex, int tileX, int tileY); // [Garage]
int HasOccupiedBay() const; // [Garage, StructureFactory, Spaceport]
void SetFactoryCargo(int bay, map_id unitType, map_id cargoOrWeaponType); // [StructureFactory, Spaceport]  [Note: If items is an SULV, RLV, or EMP Missile, it is placed on the launch pad instead of in the bay]
void DoDevelop(map_id itemToProduce); // [Factory]  [Note: Sets weapon/cargo to mapNone, can't build Lynx/Panther/Tiger/GuardPostKits]
void ClearSpecialTarget(); // [Lab]

A few are Spaceport related, but none seem to load cargo into a rocket. My guess is, the original game didn't ever use this functionality for the AI, and so there are no exported methods to do it.

It would still be possible to construct a CommandPacket which matches the Player's command to do it, and issue that. The OP2Internal project has a fair bit of info on CommandPackets. Check src/Game/CommandPacket.h. Unfortunately Outpost2DLL has no direct way to issue a CommandPacket. That functionality was split off into Outpost2App.h. It's in class TApp:
Code: [Select]
int PlaybackCommand(struct CommandPacket *, int);

We should look at merging Outpost2App.h into the same project as Outpost2DLL. Maybe as separate subfolders of the same project or something.



In terms of Unit fields, we have some text files in the SVN repository (currently offline?) in the OllyDbg/InternalData/ folder that describes a lot of detail about the Unit structure. It's messy though. It's basically a union of a bunch of different structs. Each Unit type can potentially have it's own layout. It does actually follow an inheritance hierarchy, though we've never actually worked out the full hierarchy. Fields that are common to many unit types come first.

The flags field is reasonably well understood and documented in there.

We should port those text files over to GitHub.
« Last Edit: March 31, 2019, 08:40:18 PM by Hooman »

Offline TechCor

  • Newbie
  • *
  • Posts: 34
Re: OP2 Scenario Project for C#
« Reply #53 on: April 01, 2019, 06:49:16 AM »
Hell Yeah! I reinvented the wheel! The OllyDbg confirms all those flags and the launchPadCargo. I assume HFL used an earlier version or something. The "connected to CC" flag most def isn't there, either.

CommandPacket.h doesn't appear to mention anything about transferring launchpad cargo. The only thing that might be it is TransferCargo which has an unknown variable. I guess it isn't necessary. I set unknown14 to the launch cargo and it loads the cargo. I mimic the command by doing a swap with the bay.


So that leaves two issues:

1. How to tell that a structure is disconnected.

2. HFL doesn't give me enough power. Do I desync my version by adding functionality?

Offline Crow!

  • Jr. Member
  • **
  • Posts: 52
Re: OP2 Scenario Project for C#
« Reply #54 on: April 01, 2019, 09:43:30 AM »
What is the "tubes" disable type, if not a reference to CC connection?
Speedruns, my FFIV game randomizer, and more can be found at my twitch page:
https://twitch.tv/iicrowii

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4740
Re: OP2 Scenario Project for C#
« Reply #55 on: April 01, 2019, 11:19:25 AM »
You can always submit a pull request for HFL updates.

Additionally, OP2Internal can be used with level building. Though it does currently complicate linking, and make the module not relocatable. The relocatable thing isn't normally a problem in practice though, particularly not for level DLLs. I'm planning to address those issues soon.

Offline Vagabond

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 842
Re: OP2 Scenario Project for C#
« Reply #56 on: April 01, 2019, 05:08:34 PM »
TechCor,

If you have the skill to create a function that allows loading rocket cargo via memory hacks, I would encourage you to attempt to add it to HFL via a pull request. We can review the code and hopefully incorporate it into the SDK.

Better not to diverge unless we cannot come to agreement on implementation and this seems like the right thing to add to HFL.

-Brett

Offline Arklon

  • Administrator
  • Hero Member
  • *****
  • Posts: 1223
Re: OP2 Scenario Project for C#
« Reply #57 on: April 01, 2019, 08:40:38 PM »
You can always submit a pull request for HFL updates.

Additionally, OP2Internal can be used with level building. Though it does currently complicate linking, and make the module not relocatable. The relocatable thing isn't normally a problem in practice though, particularly not for level DLLs. I'm planning to address those issues soon.

Level DLLs are actually the most susceptible to the not being relocatable thing, since they are loaded last.

Launch pad rocket is an int32 at +0x6E from the base of the internal unit structure, launch cargo (starship module loaded in rocket) is an int32 at +0x72.
« Last Edit: April 01, 2019, 08:56:28 PM by Arklon »

Offline TechCor

  • Newbie
  • *
  • Posts: 34
Re: OP2 Scenario Project for C#
« Reply #58 on: April 03, 2019, 09:29:35 PM »
Launch pad rocket is an int32 at +0x6E from the base of the internal unit structure, launch cargo (starship module loaded in rocket) is an int32 at +0x72.
How did you know it was an int32? I was having problems building a SULV after launching hacked cargo. Turns out changing the value from short to int fixed the problem.

The OllyDbg says it's 2 bytes.


Anyway, I've run into a couple issues.

1. For some reason "DoDock" sends the convec off the map. However, "DoMove" works fine. This is mostly an aesthetic problem that I'm not too concerned about right now, as the convec will still transfer its cargo and move on.

2. Robominer won't deploy. I'm calling DoBuild(map_id.CommonOreMine, beacon.GetTileX(), beacon.GetTileY()). It seems to spin in place on the beacon. Maybe it's the wrong command?

Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3194
Re: OP2 Scenario Project for C#
« Reply #59 on: April 04, 2019, 05:53:13 PM »
If you're using .DoBuild you need to issue the command 1 tile down and to the right of the beacon, as if the Robo-Miner (or GeoCon) were a ConVec.  It's a bit of a cheat, since if you watch it happen the miner appears to teleport onto the beacon when construction starts, but it's the easiest way to do it.
"As usual, colonist opinion is split between those who think the plague is a good idea, and those who are dying from it." - Outpost Evening Star

Outpost 2 Coding 101 Tutorials

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4740
Re: OP2 Scenario Project for C#
« Reply #60 on: April 04, 2019, 08:18:39 PM »
Yeah, the game doesn't provide a proper method to directly build a mine. You either have to hack it with the (+1, +1) tile offset, using a build group (AI only, I believe), or issue a command packet directly.



For the Spaceport, I see this in the InternalData notes from SVN:
Code: [Select]
Unit:Building:Spaceport
-----------------------
0x6E 4 launchPadUnitType  [SULV/RLV/EMPMissile]
0x72 2 launchCargo
0x74 2 boolRLVLanding

Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3194
Re: OP2 Scenario Project for C#
« Reply #61 on: April 04, 2019, 08:35:38 PM »
I forked HFL and am working on a DoDeployMiner method, but I'm not sure how to do the bitwise stuff to get the X and Y coordinate into the low/high byte, respectively.  Thoughts?
Code: [Select]
Type: (0x06) "ctMoBuild" Build a building (ConVec, RoboMiner, GeoCon)
------------
Size in bytes:     0x13 (19 bytes) minimum to deploy RoboMiner/GeoCon/ConVec building
Size in bytes:     0xD + numUnits*2 + numWayPoints*4
        (13 + numUnits*2 + numWayPoints*4)
Offset     Size     Description
------     ----     -----------
0x0     1     numUnits
0x1     2*X     unitID - array of size numUnits
0x3     2     numWayPoints (BYTE)
0x5     4*Y     wayPointLocation - (pixelX:15, pixelY:14)
0x9     2     buildArea.TopLeft.x (bulldozed tile)
0xB     2     buildArea.TopLeft.y (bulldozed tile)
0xD     2     buildArea.BottomRight.x (bulldozed tile)
0xF     2     buildArea.BottomRight.y (bulldozed tile)
0x11     2     (Stored to Unit.+0x6A - value 0xFFFF)
« Last Edit: April 05, 2019, 12:16:19 AM by Sirbomber »
"As usual, colonist opinion is split between those who think the plague is a good idea, and those who are dying from it." - Outpost Evening Star

Outpost 2 Coding 101 Tutorials

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4740
Re: OP2 Scenario Project for C#
« Reply #62 on: April 05, 2019, 03:27:25 AM »
Do you mean the waypoint location?
Code: [Select]
(pixelX & 0x07FFF) | (pixelY & 0x03FFF) << 15;

Ehh, actually, that is pretty awful and unnatural looking. Assuming I got that right.

Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3194
Re: OP2 Scenario Project for C#
« Reply #63 on: April 05, 2019, 09:06:55 AM »
Thanks, that gave me the push I needed to figure it out.  I also fixed DoDock while I was at it.  Take a look here.
"As usual, colonist opinion is split between those who think the plague is a good idea, and those who are dying from it." - Outpost Evening Star

Outpost 2 Coding 101 Tutorials

Offline TechCor

  • Newbie
  • *
  • Posts: 34
Re: OP2 Scenario Project for C#
« Reply #64 on: April 05, 2019, 02:36:03 PM »
Nice work. I'll take a look at it when I'm back at a testable point.


Currently implementing a trio of tasks:

CreateCommonMiningBase
CreateCommonMine
SaturateCommonMine

A mine isn't saturated if it has less than X smelters assigned to it. If there are unsaturated mines, build a smelter.
A command center has a "control area". A CC owns beacons inside the control area. If there are beacons without mines, build a mine.
If every beacon has a mine and every mine is saturated, build a new CC near a beacon to increase access.


In order to place buildings, I need to know the "connection grid" to determine where tubes need to be placed, etc. I assume how OP2 does this is unknown. If that's the case, I'm going to create my own grid that can be used as a lookup. A bit of an expensive operation - BF search from the CC checking for tubes and buildings on tiles.

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4740
Re: OP2 Scenario Project for C#
« Reply #65 on: April 06, 2019, 06:55:00 AM »
Ahh sweet. Would be good to get new functions into the development libraries.


Just had a thought about the waypoint calculation. If you used bitfields in a struct, the compiler should be able to pack the values for you. It could also properly handle signed/unsigned extensions. (I'm not sure what is needed here in regards to signed/unsigned).
Code: [Select]
struct Waypoint {
  int x:15;
  int y:14;
  int reserved:3;
};

Waypoint waypoint{pixelX, pixelY};

Offline TechCor

  • Newbie
  • *
  • Posts: 34
Re: OP2 Scenario Project for C#
« Reply #66 on: April 06, 2019, 11:34:52 PM »
Things are going pretty well.

The SVN is down, and I can't check the OllyDbg notes. I guess I should have downloaded it. There are a couple new things that I need:

1. Power output and demand. I assume this is in OP2Player.

2. UnitInfo about capacity for residences, medical centers, recreation facilities and DIRT.

I need this to determine the number of each structure that needs to be built.


Hopefully that information is there.

Offline Vagabond

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 842
Re: OP2 Scenario Project for C#
« Reply #67 on: April 07, 2019, 07:17:08 AM »
I zipped the OllyDbg folder from my local copy of the SVN repository. It may be missing a couple of changes if Hooman has updated since I pulled. He tends to update them slowly over time when researching.

-Brett

Offline TechCor

  • Newbie
  • *
  • Posts: 34
Re: OP2 Scenario Project for C#
« Reply #68 on: April 09, 2019, 07:05:28 PM »
Thanks for the OllyDbg zip. Found what I needed.

---
I would like to check if a player has a particular unit's required technology researched to determine if a task can be completed. For example, you need to research "Space Program" before you can make a Spaceport.

In the UnitInfo class in HFL, there is a function called GetResearchTopic(). The problem is I don't know what this is returning or if it is valid. It returns 69 for the Spaceport, but "Space Program" has tech ID of 5405.

I've tried looking at OllyDbg, but it doesn't appear to match what HFL is doing at all. I'm thinking it's a discrepancy between unit types (vehicles and structures). HFL seems to assume all units are the same size struct.

Can someone give me some clarity on this?


HFL UnitInfo:

https://github.com/TechCor8/OP2DotNetMissionSDK/blob/master/NativeMissionSDK/NativeSDK/HFL/Source/UnitInfo.cpp

I'm looking at DataStructure UnitTypeInfo.txt in OllyDbg.

Offline Arklon

  • Administrator
  • Hero Member
  • *****
  • Posts: 1223
Re: OP2 Scenario Project for C#
« Reply #69 on: April 09, 2019, 09:28:38 PM »
In the UnitInfo class in HFL, there is a function called GetResearchTopic(). The problem is I don't know what this is returning or if it is valid. It returns 69 for the Spaceport, but "Space Program" has tech ID of 5405.
That's because the tech index in that context is by array index, which boils down to the order in which techs are defined in the tech .txt, rather than tech ID.

Quote
I've tried looking at OllyDbg, but it doesn't appear to match what HFL is doing at all. I'm thinking it's a discrepancy between unit types (vehicles and structures). HFL seems to assume all units are the same size struct.
The unit entries in the internal unit array are all the same size, based on sizeof mapGeneralUnit (max map_id) I believe.

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4740
Re: OP2 Scenario Project for C#
« Reply #70 on: April 10, 2019, 10:42:53 AM »
We should get those txt files moved to GitHub.

A long while back, I was paring down the txt files as that information got added into what is now the OP2Internal project. Effectively functional documentation, rather than simple text. It may be a good alternate source of information for some things. Though the Unit and UnitInfo stuff was not really cleaned up enough to port over effectively.

In terms of storage, the game seems to use arrays of unions of all sub-types, so you effectively get an array of fixed sized data, even though the fields within each chunk have variable meaning based on unit type. Each Unit has 120 bytes of storage, even though not all unit types use the full 120 bytes. More like the largest Unit type used up to 120 bytes. UnitType info has something similar going on.

As Arklon stated, the research numbers are index numbers into the research array data. OP2Internal likely has some good detail there.


Offline Vagabond

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 842
Re: OP2 Scenario Project for C#
« Reply #71 on: April 12, 2019, 07:49:57 PM »
Sirbomber,

Did you want to move your new HFL code into a branch and issue a PR with HFL for review and merging (functions DoDeployMiner and DoDock). I can manually add them, but it would take the credit from you.

Don't want to derail topic, the fix was just posted in here.

-Brett

Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3194
Re: OP2 Scenario Project for C#
« Reply #72 on: April 12, 2019, 09:30:41 PM »
I'll PM you about this, to not derail the thread.
"As usual, colonist opinion is split between those who think the plague is a good idea, and those who are dying from it." - Outpost Evening Star

Outpost 2 Coding 101 Tutorials

Offline TechCor

  • Newbie
  • *
  • Posts: 34
Re: OP2 Scenario Project for C#
« Reply #73 on: April 12, 2019, 09:41:23 PM »
Just want to let you guys know that there are a bunch of HFL additions on the C# project including:

Research/TechInfo files (Research)
Player structure capacities and status info (PlayerEx)
DoBuildWall (UnitEx)
LaunchPadCargo (UnitEx)
Mining beacon data (UnitEx)

I won't be getting around to creating a proper fork for quite some time, so it could be useful to grab those whenever. I suppose it's possible only I will find those things useful.

--
While I am here, anybody have a good way of detecting when a unit gets stuck?

Sometimes I'll have a situation where a unit will want to move to an unreachable location. Maybe they were ordered to go somewhere, and now a building is in the way. Instead of giving up, it spins in place. I need to detect that this is happening and order it to stop so it can be reassigned.

---
TethysGame::GetRand appears to be returning 0 after the first tick. Is this expected behavior? I may switch to C# rand to get around this. I'm trying to randomize guard post types.
« Last Edit: April 13, 2019, 10:09:06 PM by TechCor »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4740
Re: OP2 Scenario Project for C#
« Reply #74 on: April 15, 2019, 02:06:20 AM »
If you're not using the build in Rand(), there's a pretty good chance multiplayer games will desync.

I believe Rand should return from 0 (inclusive) up to the max value (exclusive). Are you sure it's not behaving correctly? You're not messing with the seed, are you? The build in random number generator should auto seed at game start, based on the system time. If you try to re-seed it, you basically reset the random number sequence. Continually reseeding means it will continually return the same sequence of numbers.

Not sure about stuck units.