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.
// 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:
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.
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:
// 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?
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)
// 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);
}
}
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:
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.
Well, you might be able to use an EscapeTrigger:
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...