Author Topic: Land Rush With Colonists Inside Evac Transports  (Read 4077 times)

Offline gwyned

  • Newbie
  • *
  • Posts: 17
Land Rush With Colonists Inside Evac Transports
« on: August 03, 2009, 04:28:24 PM »
Heya fellow Outpost programmers!

I've been slowly teaching myself how to code single player Colony games, mostly by reverse-engineering other people's code, and I've managed to put together a fairly decent combat-less Colony game.  But, in the process, I had an idea and wondered about whether it is possible or not.

Basically, in a Land Rush start, have one or more Evacuation Modules included.  You begin without any people (and thus have to disable this as a failure condition), and gain your starting population by moving the Evacs to your newly built Command Center.

I know just enough about Outpost2 dlls to know this would involve several different scripts to get working properly, if it is even possible at all.  Really, it doesn't seem like it's that different than moving a vehicle next to a particular structure during the regular single-player campaigns.  So my questions are this:

1. Is this possible?

2. How would one go about making this happen?

3. Has anyone ever attempted something similar? If so, is he/she willing to share their code with me?

Thanks for the help.

Offline Hidiot

  • Hero Member
  • *****
  • Posts: 1018
Land Rush With Colonists Inside Evac Transports
« Reply #1 on: August 03, 2009, 05:45:56 PM »
In my sleepy state, I will try to leave a response.

In my head, it is doable. The way I'd do ti is assign a standard number of people to each evac Transport, say... 5 Scientists, 10 Workers and 10 children.

I'd then create Evac Transports and assign them some Colonist cargo, amount of 25.

next, I'd run an AI Script check for a CC, or a specific building I want to unload at. Then check its surroundings for an Evac Transport with cargo and add the colonists to the total population.


I'm sure there's better ways, but that's off the top of my head. Everything I've talked about has a way of being done, I just don't have the time to detail.  
"Nothing from nowhere, I'm no one at all"

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Land Rush With Colonists Inside Evac Transports
« Reply #2 on: August 03, 2009, 06:50:55 PM »
I don't think there is any cargo to set for evacuation transports.

I believe this can be done, by not setting up normal failure conditions at game start, but only after the number of colonists are set. You might also need a bit of a delay between giving the colonists, and setting up the failure triggers, as you may need time for them to activate the CC. That can be accomplished with a time trigger.


In InitProc, you probably want to set a failure condition in case the evac transport is destroyed. You may also want something for failure if the CC/kit/convec is destroyed, or it is otherwise impossible to get the base going (such as no SF, or no ConVecs or Vehicle factory). Also setup a trigger that detects when the evac transport is placed next to the CC. You might need to first detect when the CC is placed with some initial trigger, and then setup another trigger with the coordinates or unit that the evac needs to move next to.

When the evac moves next to the CC, then gives the colonists. You will probably also want to setup the standard failure conditions here, and likely remove/disable/delete the old ones. As you may need to delay activation of the new failure conditions, setup a time trigger that just fires in 4 ticks or so. In the callback of that trigger, setup the normal failure conditions. Note that you might want to remove the old failure conditions when giving the colonists and setting up the time trigger. That will prevent cases where they self destruct the evac transport, and lose before the time trigger is allowed to fire.


I can't think of the names of all the triggers to use off the top of my head, but you can probably get somewhere with some experimentation.
 

Offline Hidiot

  • Hero Member
  • *****
  • Posts: 1018
Land Rush With Colonists Inside Evac Transports
« Reply #3 on: August 04, 2009, 05:13:25 AM »
I never tried, but remember mission 1 from the campaign. Evac Transports have a label with Colonists and cargo of 25. Dynamix did it, we should be able to do it :)

EDIT: Eh, ok, the Cargo amount is not displayed.  Still think I saw it somewhere... could be my imagination.


I'm also curious about something related to this. How can I get the coordinates of an object I'm looking for? F.e. I'm looking for a CC to get its coordinates so that I can use them later for other things (building relative to the CC and such).
« Last Edit: August 04, 2009, 05:14:35 AM by Hidiot »
"Nothing from nowhere, I'm no one at all"

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Land Rush With Colonists Inside Evac Transports
« Reply #4 on: August 04, 2009, 11:06:36 AM »
Oh, I'd have tried the obvious "Unit.Location()". :P

I was also thinking the following functions would be useful. Normally these functions are used with scout missions where you have to scan stuff, but I assume they should work for evac transports.
Code: [Select]
// Special Target Trigger/Data
OP2 Trigger __fastcall CreateSpecialTarget(int bEnabled, int bOneShot, Unit& targetUnit /* Lab */, map_id sourceUnitType /* mapScout */, const char* triggerFunction);
OP2 void __fastcall GetSpecialTargetData(Trigger& specialTargetTrigger, Unit& sourceUnit /* Scout */);

You'll notice that you can get the evac transport unit that caused the trigger to fire using the second function. This can allow you to keep track of which transports are loaded/unloaded when there is more than one.

For detecting the placement of the CC, I'd probably use:
Code: [Select]
OP2 Trigger __fastcall CreateBuildingCountTrigger(int bEnabled, int bOneShot, int playerNum, int refCount, compare_mode compareType, const char* triggerFunction);
Then use a PlayerBuildingEnum to actually find the Unit, and get it's Location.
 

Offline gwyned

  • Newbie
  • *
  • Posts: 17
Land Rush With Colonists Inside Evac Transports
« Reply #5 on: August 04, 2009, 03:24:22 PM »
Wow.  Okay.  Thanks for the help...

Of course, reading this makes me realize I have a long way to go before I could actually code this myself...  :lol:

Like I said, most of what I've done so far is simply to reverse-engineer other people's code.  I can look at the functions above and see the gist of how they work, but I am no where near proficient enough yet to actually understand all the nuances.

It would probably help if I had more than a very basic understanding of C++.

Offline Hidiot

  • Hero Member
  • *****
  • Posts: 1018
Land Rush With Colonists Inside Evac Transports
« Reply #6 on: August 04, 2009, 03:35:10 PM »
Just how basic? To me, I have a very basic knowledge of C++, but I can still code, having started out asking a lot of questions and being helped by Hooman here a lot (amongst others).
"Nothing from nowhere, I'm no one at all"

Offline gwyned

  • Newbie
  • *
  • Posts: 17
Land Rush With Colonists Inside Evac Transports
« Reply #7 on: August 04, 2009, 05:26:17 PM »
Quote
Just how basic? To me, I have a very basic knowledge of C++, but I can still code, having started out asking a lot of questions and being helped by Hooman here a lot (amongst others).

I've never actually learned C++, but I have a decent understanding of Basic.  I've programmed several shortcut programs into a scientific calculator to do things like replicate rolling a die, or handling multiple calculations given certain variables, and that sort of thing.  I understand enough that I can take a piece of code and track down how it is interacting with other lines and figure out which parameters call which function (like deciphering the Tethys commands with mining beacons or the like).  I've been using CodeBlocks and the SDK, but probably what is holding me back the most is understanding all the various parameters for each command.  

Take Hooman's Special Target/Trigger data, for example:
Code: [Select]
// Special Target Trigger/Data
OP2 Trigger __fastcall CreateSpecialTarget(int bEnabled, int bOneShot, Unit& targetUnit /* Lab */, map_id sourceUnitType /* mapScout */, const char* triggerFunction);
OP2 void __fastcall GetSpecialTargetData(Trigger& specialTargetTrigger, Unit& sourceUnit /* Scout */);

I could place those commands into the right places in the Outpost DLL, and can see that the CreateSpecialTarget requires an integer, followed by another integer, followed by a reference to a particular structure, followed by a reference to a specific unit, and then calls a particular function.  I even recognize the tags within the command to denote comments that are not part of the actual code.  But how to obtain those references, or even which integers make sense for the first components, isn't very clear to me.  

Granted, if I saw it in a particular mission, I could probably do some tests and figure out how it functioned and then tweak it to do something differently.  But, again, that's a lot more reverse-engineering and less actual coding.

I have no interest in learning how to code C++ really, but if there's some basics that would be directly applicable to creating Outpost dlls through Codeblocks, I'd be happy to do some reading/studying on my own.

Does that make sense?
« Last Edit: August 04, 2009, 05:27:45 PM by gwyned »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Land Rush With Colonists Inside Evac Transports
« Reply #8 on: August 04, 2009, 10:23:07 PM »
Keep in mind what the parameter names are. Sometimes there is a naming convention that is followed. Usually "int" values whose name starts with a "b", followed by an uppercase letter starting a new word means it's a "boolean" value. Boolean values only take two values: 0 = false, 1 = true (or "non-zero" = true).

For boolean parameters, you should pass either "true" or "false". You can also pass 1 or 0, but that's a little less clear.

For instance, if bOneShot is true, then the trigger will only fire once, and then get disabled. This could be used in a time trigger for a single event, such as a volcanic eruption some number of ticks into the game. If instead bOneShot was set to false, then the trigger would reset itself after firing, and would be able to fire again. This could be used to create disasters at regular intervals. (You probably want a range of times here, which would be the second CreateTimeTrigger function that can specify a min and max number of ticks between firing, and it will choose a random value in that range).


The map_id parameter is an "enum". An enum is just a list of named constants. You can look in MapIdEnum.h from the SDK to see all possible values.


Similarly, the Unit class is defined in Unit.h in the SDK. This is only really a stub class that just points to the real internal unit class. As such, you can't create a unit with this class, but only obtain a handle to a pre-existing unit. For instance, TethysGame::CreateUnit will fill in the passed Unit object, so it can be used to refer to the unit that was just created. You can also obtain unit handles using the enumerator classes (PlayerUnitEnum, PlayerBuildingEnum, PlayerVehicleEnum, GroupEnumerator, InRangeEnumerator, InRectEnumerator, LocationEnumerator, ClosestEnumerator). Again, check TethysGame.h and Enumerators.h in the SDK.


The last parameter of the CreateTriggerX functions is the name of the callback function. When the trigger fires, this is the function that gets called to handle the event. Note that for Outpost 2 to find this function, it must be exported from your DLL. Hence it will need "EXPORT" in front of the function definition. For instance, suppose you want to create disasters at regular intervals. You'd define a callback function that chooses a random location, and possibly random disaster type and random disaster strength, and create the disaster. You'd then set that function as the callback for a time trigger. Then whenever the time trigger fires, Outpost 2 will call your function, and your function will create a new disaster.

 

Offline gwyned

  • Newbie
  • *
  • Posts: 17
Land Rush With Colonists Inside Evac Transports
« Reply #9 on: August 17, 2009, 04:20:18 PM »
Alright, after a busy few weeks, I'm finally back to tinkering my way through this project.  Here are my latest issues:

1. How does one create the Colonists "cargo" on a Evacuation Transport? Is this actual cargo, or is it just some flag that shows up with the vital stats?

2. With Cargo Trucks, the game clearly distinguishes between one carrying a particular cargo and ones that don't.  I tested this with a simple trigger.  Is the same thing true of Evacuation Transports? I hope so...otherwise, I don't look forward to coding some way of differentiating between transports that have already unloaded colonists and those that have not.

Still got a lot to learn: but at least in theory this appears to work - on my current map, moving an Earthworker next to the newly-built Command Center causes 500 children to be added to the total Colonists.    :heh:
« Last Edit: August 17, 2009, 04:21:31 PM by gwyned »

Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3238
Land Rush With Colonists Inside Evac Transports
« Reply #10 on: August 17, 2009, 09:54:17 PM »
Set the Evac Transport's cargo to "mapInterColonyShuttle" to make it say Cargo: Colonists.

You can't load/unload Evacuation Transports at a dock; you'll have to manually code it somehow.
"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 speaker

  • Newbie
  • *
  • Posts: 26
Land Rush With Colonists Inside Evac Transports
« Reply #11 on: August 17, 2009, 11:21:20 PM »
not that i know what im talking about  :whistle:  but they managed to load colonists into the evacuation transport in Eden's mission to save the scientists/kill the spaceport, so its definitely possible
Speaker for the Dead
pɐǝp ǝɥʇ ɹoɟ ɹǝʞɐǝdS

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Land Rush With Colonists Inside Evac Transports
« Reply #12 on: August 18, 2009, 12:06:25 AM »
Tell me exactly what mission, and if possible what conditions in the mission produce the behavior of interest, and I can probably figure out how they did it for you.

Oddly enough, I'm too lazy to bother without at least something to uniquely identify the mission dll.
 

Offline Hidiot

  • Hero Member
  • *****
  • Posts: 1018
Land Rush With Colonists Inside Evac Transports
« Reply #13 on: August 18, 2009, 09:24:05 AM »
Eden 11 and Plymouth 10.
"Nothing from nowhere, I'm no one at all"

Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3238
Land Rush With Colonists Inside Evac Transports
« Reply #14 on: August 18, 2009, 10:41:53 AM »
You'd need special target triggers.

Something like this MIGHT work:
(Note that this was written on the fly and is untested, so take it with a grain of salt)
Code: [Select]
// This code creates special target triggers on a pre-defined Command Center so we can create the illusion of loading/unloading Evacuation Transports.  I experimented with making it check for ALL player-owned CC's, but...

// Create the special CC and the SpecialTarget function - in InitProc
Unit PlayerCC;
Trigger ETransTrig;

TethysGame::CreateUnit(PlayerCC, mapCommandCenter, LOCATION(x+31, y-1), 0, mapNone, 0);
ETransTrig = CreateSpecialTarget( 1, 0, PlayerCC, mapEvacuationTransport, "LoadUnloadColonists");

// Load/unload those colonists! - NOT in InitProc
// For this example code, we're assuming each Evac Trans holds 10 children, 10 workers, and 5 Scientists
SCRIPT_API void LoadUnloadColonists()
{
Unit EvacTrans;
GetSpecialTargetData(ETransTrig, EvacTrans);
if (EvacTrans.GetCargo == mapInterColonyShuttle)
{
  TethysGame::AddMessage(-1, -1, "Our Colonists have arrived safely!", 0, sndRes1_sel);
  Player[0].SetKids( Player[0].Kids() + 10);
  Player[0].SetWorkers( Player[0].Workers() + 10);
  Player[0].SetScientists(Player[0].Scientists() + 5);
  EvacTrans.SetCargo(mapNone, mapNone);
}
else
{
  TethysGame::AddMessage(-1, -1, "Our Colonists are ready to be evacuated!", 0, sndRes1_sel);
  Player[0].SetKids( Player[0].Kids() - 10);
  Player[0].SetWorkers( Player[0].Workers() - 10);
  Player[0].SetScientists(Player[0].Scientists() - 5);
  EvacTrans.SetCargo(mapInterColonyShuttle, mapNone);
}
}
« Last Edit: August 18, 2009, 10:42:06 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 speaker

  • Newbie
  • *
  • Posts: 26
Land Rush With Colonists Inside Evac Transports
« Reply #15 on: August 18, 2009, 03:04:57 PM »
Quote
Tell me exactly what mission, and if possible what conditions in the mission produce the behavior of interest, and I can probably figure out how they did it for you.

Oddly enough, I'm too lazy to bother without at least something to uniquely identify the mission dll.
Quote
Eden 11 and Plymouth 10.
this

and it is triggered by moving the convec next to the advanced lab, where it spins its wheels for a few seconds and then "cargo: colonists" appears
« Last Edit: August 18, 2009, 03:05:42 PM by speaker »
Speaker for the Dead
pɐǝp ǝɥʇ ɹoɟ ɹǝʞɐǝdS

Offline gwyned

  • Newbie
  • *
  • Posts: 17
Land Rush With Colonists Inside Evac Transports
« Reply #16 on: August 18, 2009, 05:06:18 PM »
An Evacuation Transport set with the Colonists cargo is not detected by the CreateSpecialTarget trigger as mapEvacuationTransport.  This same phenomena can be observed by making a CreateSpecialTarget trigger with mapCargoTruck.  If the truck is loaded with metals, food, etc., it will not meet the condition and nothing will happen.  If it is empty, it will trigger.

So, what must mapEvacuationTransport be changed to in order to properly detect the loaded transports?

Also, my version is a Land Rush game, so you have to detect the Command Center once it is built, not simply build it upfront.  The version I have at the moment simply gives the whole colony population to Player0 once the Evac Transport is adjacent to the Command Center.  It works, but it somewhat rough still.

I am also having problems with crashes if I remove the fail conditions of having no population but still include a population victory condition.  The dll loads and runs fine, but as soon as I build a Command Center, it goes for a few ticks and then crashes.  Is this some sort of built in limit - ie, does a population victory condition require a 0 population failing condition.  Or have I messed up somthing in my code?
« Last Edit: August 18, 2009, 05:07:08 PM by gwyned »

Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3238
Land Rush With Colonists Inside Evac Transports
« Reply #17 on: August 18, 2009, 07:53:12 PM »
You messed something up.
"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 gwyned

  • Newbie
  • *
  • Posts: 17
Land Rush With Colonists Inside Evac Transports
« Reply #18 on: August 19, 2009, 07:22:25 AM »
Quote
You messed something up.
Alright.  I changed the enumeration code that detected the CC to terminate after it had found it the first time, and that change stopped the crashes when the CC is built with the population victory.  Apparently I know just enough to fix problems without really understanding why that particular fix did it.

I would still love if someone could figure out how to create a trigger that would recognize a loaded Evacuation Transport.  Otherwise, things are humming along just fine now.  I expect to release a beta of this map pretty soon...

Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3238
Land Rush With Colonists Inside Evac Transports
« Reply #19 on: August 19, 2009, 08:17:06 AM »
I don't know.  Try having one SpecialTarget trigger search for Evacuation Transports, and another search for InterColonyShuttle?  I doubt it will work, but...

This may have been done intentionally to prevent using the same vehicle for multiple objectives... Though really, it should just check a vehicle AND its cargo...

Edit: Also, it was probably crashing because you went past the stub limit by creating the same trigger over and over again.
« Last Edit: August 19, 2009, 08:18:31 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: 4955
Land Rush With Colonists Inside Evac Transports
« Reply #20 on: August 19, 2009, 11:48:08 PM »
Eden 11 uses a SpecialTargetTrigger. It calls CreateSpecialTarget to check for an evacuation transport. It loads the vehicle by calling GetSpecialTargetData to get the Unit that caused the trigger to activate, and then it calls Unit.SetCargo(0x27, 0).

The CreateSpecialTarget call seems to be in response to the building being scanned by a scout. It calls PlaceMarker to place a beaker marker, calls CreateSpecialTarget, and then calls AddMessage to tell the player "Data transmitted: scientists located".


I took a quite look at the special target trigger code. As far as I can tell, it doesn't seem to check a unit's cargo. It only checks based on unit type. It shouldn't matter if a unit is loaded with cargo or not, it should still be detected just the same.

Can you double check and confirm different behavior between two tests where the only change is whether a unit is loaded with cargo or not? (Use Unit.SetCargo).

Offline gwyned

  • Newbie
  • *
  • Posts: 17
Land Rush With Colonists Inside Evac Transports
« Reply #21 on: August 20, 2009, 05:44:45 PM »
Quote
Eden 11 uses a SpecialTargetTrigger. It calls CreateSpecialTarget to check for an evacuation transport. It loads the vehicle by calling GetSpecialTargetData to get the Unit that caused the trigger to activate, and then it calls Unit.SetCargo(0x27, 0).

The CreateSpecialTarget call seems to be in response to the building being scanned by a scout. It calls PlaceMarker to place a beaker marker, calls CreateSpecialTarget, and then calls AddMessage to tell the player "Data transmitted: scientists located".


I took a quite look at the special target trigger code. As far as I can tell, it doesn't seem to check a unit's cargo. It only checks based on unit type. It shouldn't matter if a unit is loaded with cargo or not, it should still be detected just the same.

Can you double check and confirm different behavior between two tests where the only change is whether a unit is loaded with cargo or not? (Use Unit.SetCargo).
Here's the code I use to add Colonists to Player0 once the Evac Transport is detected:

Code: [Select]
void AIProc()
{
    Unit CC;
    PlayerBuildingEnum buildingEnum(0, mapCommandCenter);
    while (buildingEnum.GetNext(CC)>0)
    {
        if (scriptGlobal.FirstCC==0)
    {
        scriptGlobal.FirstCC = 1;

     if (CC.GetType() == mapCommandCenter)
     {
            CreateSpecialTarget(1, 0, CC, mapEvacuationTransport, "AddColonists");
     }
    }
    }
}

SCRIPT_API void AddColonists()
{
    switch(Player[0].Difficulty())

{
case 0:     //Easy
    Player[0].SetKids(60);
    Player[0].SetWorkers(40);
    Player[0].SetScientists(30);
    break;

    case 1:  // Normal
    Player[0].SetKids(55);
    Player[0].SetWorkers(35);
    Player[0].SetScientists(20);
    break;

    case 2:  // Hard
    Player[0].SetKids(50);
    Player[0].SetWorkers(30);
    Player[0].SetScientists(15);
    break;

}
    CreateTimeTrigger(1,1,100,"Morale");
}

If the Evacuation Transport has been given the following command:

Unit1.SetCargo(mapInterColonyShuttle, mapNone);

The trigger does not activate when the Evac is adjacent to the Command Center.  If this command is commented out, the trigger does activate properly.

Hope that helps.
« Last Edit: August 20, 2009, 05:45:40 PM by gwyned »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Land Rush With Colonists Inside Evac Transports
« Reply #22 on: August 20, 2009, 10:19:51 PM »
Hmm, quite right. I'll look into it.

Btw, you might have been better off using a building count trigger than AIProc.
Also, you'll probably want to make that SpecialTarget Trigger a one-shot trigger. As you have it know, they can keep unloading more colonists by moving the transport back and forth. Change the second parameter when creating the trigger.



Edit: A Unit only checks if it's triggered a SpecialTarget trigger when it's completed a "ctMoSpecialWait" cycle. I guess loaded trucks never enter this cycle.

It might take a fair bit more effort to find the code that controls this though.
 
« Last Edit: August 20, 2009, 10:32:03 PM by Hooman »

Offline gwyned

  • Newbie
  • *
  • Posts: 17
Land Rush With Colonists Inside Evac Transports
« Reply #23 on: September 20, 2009, 07:13:42 AM »
Any more luck (or ideas) on how to build a trigger that recognizes a loaded Evacuation Transport? It must be possible, as several times in the campaign a Victory Condition includes bringing a loaded Transport back to a particular spot (heck, this is true even in Eden 1, for example).

Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3238
Land Rush With Colonists Inside Evac Transports
« Reply #24 on: September 20, 2009, 08:45:08 AM »
Well, you might be able to use an EscapeTrigger:
Code: [Select]
CreateEscapeTrigger(int boolEnable, int boolNoRepeat, int playerNum, int x, int y, int width, int height, int refValue, enum map_id unitType, int cargoType, int cargoAmount, char const *triggerFunction);

As you can see, this checks for a specific vehicle AND its cargo at a specific location.  You won't have the nice "spinning wheels to make it look like we're doing something" animation, but oh well.  I don't know what you'd put in for cargoAmount, though...
"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