Author Topic: Counting Truckloads  (Read 3501 times)

Offline jcj94

  • Sr. Member
  • ****
  • Posts: 407
    • http://techfusion-279.com
Counting Truckloads
« on: April 01, 2011, 04:52:14 PM »
Code: [Select]
CreateCountTrigger(int boolEnable, int boolNoRepeat, int playerNum, enum map_id unitType, enum map_id, int refCount, enum compare_mode compareType, char const *triggerFunction);

this is the code I am using for counting truckloads for Ore degeneration.

If you want to help me sort through/ fix problems I may/may not run into, hop on the old IRC.

When I get done, I'll post an example for you guys.
« Last Edit: April 01, 2011, 05:08:19 PM by jcj94 »

Offline Flashy

  • Sr. Member
  • ****
  • Posts: 391
Counting Truckloads
« Reply #1 on: April 01, 2011, 05:27:14 PM »
I don't think that will help, it only counts the trucks that are there at the moment
Praise the mighty light towers!!!

Offline jcj94

  • Sr. Member
  • ****
  • Posts: 407
    • http://techfusion-279.com
Counting Truckloads
« Reply #2 on: April 01, 2011, 05:33:42 PM »
Do you know if there is another, I saw some, but am unsure of what they do entirely..

Code: [Select]
CreateResourceTrigger(int boolEnable, int boolNoRepeat, enum trig_res resourceType, int refAmount, int playerNum, enum compare_mode compareType, char const *triggerFunction);

I;m not sure If i can use it for a particular mine or something, after all I am still learning here.

And wouldn't that do the job anyway?

or do I need to create my own trigger type that checks how many times any cargo truck has been over the mine.  They would do the same job, and count how many truckloads wouldn't they?
« Last Edit: April 01, 2011, 05:40:14 PM by jcj94 »

Offline Hidiot

  • Hero Member
  • *****
  • Posts: 1018
Counting Truckloads
« Reply #3 on: April 01, 2011, 06:28:09 PM »
You'd need to count number of docks over time.

A crude way of doing it that I can think of is creating a repeating point trigger that keeps track of the number of cargo trucks that have passed (hopefully by docking) on the mine's dock.
"Nothing from nowhere, I'm no one at all"

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Counting Truckloads
« Reply #4 on: April 02, 2011, 02:55:08 AM »
Mines already count truck loads to implement the ore changing over time. Use a memory hacking approach to read the value.

Having a unit reference to either the mine or the beacon itself would be useful here. I'm not sure which one you'd need off the top of my head though. Probably the beacon, which is a bit harder to get. I'd have to look it up if you're interested in that approach, unless someone else has the info handy.
 

Offline jcj94

  • Sr. Member
  • ****
  • Posts: 407
    • http://techfusion-279.com
Counting Truckloads
« Reply #5 on: April 02, 2011, 09:46:52 AM »
Much appreciated from the both of you if you'd be so kind as to help.

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Counting Truckloads
« Reply #6 on: April 03, 2011, 02:21:11 AM »
Here's the note I made on the mining beacon unit:

Code: [Select]
Unit:MiningBeacon
-----------------
0x58 4 int numTruckLoadsSoFar
0x5C 4 int barYield
0x60 4 int variant
0x64 1 char oreType  [0 = common, 1 = rare]
0x65 1
0x66 1
0x67 1 char surveyedBy  [player bit vector]


If you can find some kind of handle to the beacon, you can read the int value at offset 0x58. To change the yield, play with the other values (and possible reset numTruckLoadsSoFar).

I don't know how well the game will pick up changes, but I imagine there shouldn't be much problem. It might recalculate current ore yields from those variables each time they're needed.


I don't remember if the default enumerators can return mining beacon units, and I doubt there is another way to get the unit's handle using the usual level API. You might want to experiment with that first.

Once you have a unit handle, you should be able to convert it to a unit object address. There should be examples on here somewhere, and other people that can help with that. From there it's just a matter of offsetting to the required fields. I'm too tired to go into any details right now, and you need to find a way to get a unit handle first anyway.
 

Offline jcj94

  • Sr. Member
  • ****
  • Posts: 407
    • http://techfusion-279.com
Counting Truckloads
« Reply #7 on: April 04, 2011, 04:56:52 PM »
I have been experimenting with a crude way to shift the mine.

What I was planning on doing was:
TethysGame::CreateUnit(m0013, mapMiningBeacon...
and destroying all units m(mine beacon #)(starting bar #) and degrading them after X truckloads.
so far though I havn't been able to get a trigger that looks like it will work to.. extract(?) the truckload amounts for each mine.

I'm more of a "seeing trigger bases"(like the def's that popup in VCExpress).  I like it because it feels more tangible, and I'm still learning C++.   I know enough java to make a robot work, but that is using different levels of meaning on a cRIO, not game programming.

I know, I need to read the tutorials and REMEMBER stuff, but ATM, I've not had enough time to do so.

Offline Flashy

  • Sr. Member
  • ****
  • Posts: 391
Counting Truckloads
« Reply #8 on: April 05, 2011, 10:35:38 AM »
Yielded no results when trying to use Enumerators for mining beacons. But using some brute force enumeration, i got some Unit handles that return mapMiningBeacon on GetType()
Code: [Select]
Unit x;
for(int i=0;i<2048;++i)
{
x.SetId(i);
if(x.IsLive())
{
  char buffer[60];
  scr_snprintf(buffer, 60, "Unit type: %d", x.GetType());
  TethysGame::AddMessage(-1, -1, buffer, 0, 0);
}
}

But I had no success trying to obtain the information hooman mentioned. I used HFL because it has a unitArray pointer, but I didn't get what I want.
Praise the mighty light towers!!!

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Counting Truckloads
« Reply #9 on: April 07, 2011, 12:00:51 AM »
Ahh, that should work.

You could perhaps wrap that code up into an enumerator class if you wanted.


Once you have a unit index (unitIndex = unit.unitId), you can convert it to a unit pointer provided you know the base address of the unit array. If HFL provides that, then sure. This is normally simple code like this:
Code: [Select]
unitPtr = &unitArray[unitIndex];
However, the unit array might not be a typed properly (I'm not sure), and so indexing it might not provide the correct offset. In which case you can do the indexing manually. You'll also need a bit of casting. To use byte level offsets you should cast to a byte sized data type, such as char. You'll probably need to cast back to the type of  your unit pointer, depending on what it is. If you use char*, then you can probably avoid that cast. I'll just fill in "UnitType*" for that part of the cast since it will depend on your pointer declaration:
Code: [Select]
unitPtr = (UnitType*)((char*)unitArray + unitIndex * 120);

Now to access the fields off the unitPtr, you'll need a bit more casting and offsets. I'll favour extra casts for clarity of offsets, although you can probably code this a little more directly if you play with the offsets to match the size of the casted type. I find that a bit hard to read though, so here's the doubly casted way:
Code: [Select]
numTruckLoads = *(int*)((char*)unitPtr + 0x58);

That should get you the value you're looking for.
 

Offline TH300

  • Hero Member
  • *****
  • Posts: 1404
    • http://op3game.net
Counting Truckloads
« Reply #10 on: April 29, 2011, 10:24:11 AM »
I found all mining beacons on one of my own maps with code like this:

Code: [Select]
PlayerUnitEnum puEnu(6);
Unit unit;
while (puEnu.GetNext(unit))
{
    if (unit.GetType() == mapMiningBeacon)
    {
        printf("Mining Beacon found!\n");
    }
}

That should be faster than iterating over the whole unit array.

Apparently thats the best way of doing it. The code that op2 uses internally is quite similar. (yes, its ridiculous, but true. You can see it in the function at 436AE0. It iterates over all Gaia units to find a mining beacon or magma vent at a certain location)

Furthermore, I found that the game seems to store information like yield and variant not only in the mining beacon, but also in the mine. I Don't know how this data is synchronized, but this could mean that changing the data in the mine struct will automatically change it for the beacon.
« Last Edit: April 29, 2011, 10:24:45 AM by TH300 »

Offline jcj94

  • Sr. Member
  • ****
  • Posts: 407
    • http://techfusion-279.com
Counting Truckloads
« Reply #11 on: April 29, 2011, 12:48:23 PM »
or changing it in the mine could change it for the beacon.

Yes, I am still working on this, just, everything codewise has taken a bit of a backseat until I get some more time off to code and such.

Offline TH300

  • Hero Member
  • *****
  • Posts: 1404
    • http://op3game.net
Counting Truckloads
« Reply #12 on: April 29, 2011, 04:52:46 PM »
After I got a unit handle to the beacon, I realized that it is indeed something else than the Unit class that op2 uses internally (the fact that the unit handle has class "Unit" and in Hooman's Ollydbg comment file the internal Unit has class "Unit" is a bit confusing).

Anyways, I was able to retrieve a pointer to the beacon data fields of the internal Unit class. First I defined this struct (which does not resemble op2 internals, but is easier to understand)
Code: [Select]
struct BeaconData
{
    int numTruckLoadsSoFar;
    int barYield;
    int variant;
    char oreType;
    char unknown1;
    char unknown2;
    char surveyedBy;
};

You see that these are the fields of the MiningBeacon class, starting at 0x58. I use this to make use of the pointer that I retrieve:

Code: [Select]
BeaconData *p = (BeaconData *) ((int) (*unitArray) + (unit.unitID*120) + 0x58);

The unitArray pointer is defined in HFL. If you want to use this code without HFL, you'll have to enter the address manually.

I can now easily access the information:

Code: [Select]
printf("Truck Loads so far: %i  Yield: %i  Variant: %i  Ore Type: %s\n", p->numTruckLoadsSoFar, p->barYield, p->variant, (p->oreType) ? "Rare" : "Common");