Author Topic: Outpost 2 DLL Programming  (Read 15727 times)

Offline gpgarrettboast

  • Administrator
  • Hero Member
  • *****
  • Posts: 553
Outpost 2 DLL Programming
« on: April 09, 2004, 01:28:20 AM »
In this forum, you can post code that may help one another figure out the DLLs, weather its the SDK or hacking.

But to keep this neat, pleast use the CODE tags like this:

Code: [Select]
TethysGame::SetVortex(24,35,26,37,3,5);

^ (Not real Code... well, kinda. I didn't have access to any. lol)

EDIT:
Oops, I accidently clicked edit. lol
« Last Edit: April 14, 2004, 07:21:39 AM by gpgarrettboast »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #1 on: April 09, 2004, 01:39:00 AM »
Basic initialization

Code: [Select]
SCRIPT_API int InitProc()
{
_Player *Player, *Computer;

Player = &::Player[0];
Computer = &::Player[1];

Player->GoEden();
Player->SetColorNumber(0);

Player->SetOre(5000);
Player->SetFoodStored(3000);
Player->SetWorkers(28);
Player->SetScientists(13);
Player->SetKids(15);
Player->CenterViewOn(60, 210);

Computer->GoPlymouth();
Computer->SetColorNumber(1);

Computer->SetOre(5000);
Computer->SetFoodStored(3000);
Computer->SetWorkers(28);
Computer->SetScientists(13);
Computer->SetKids(15);

TethysGame::ForceMoraleGood(-1);
TethysGame::SetDaylightMoves(-1);
TethysGame::SetDaylightEverywhere(0);
TethysGame::SetCheatFastUnits(0);
TethysGame::SetCheatFastProduction(0);
TethysGame::SetCheatUnlimitedResources(0);
TethysGame::SetCheatProduceAll(0);

Edit: Obsolete casting hack removed. SetDaylightMoves misunderstanding corrected (the parameter is a player number, not a boolean value, -1 means everyone). Also, there are better ways to do this now.
« Last Edit: December 09, 2004, 07:26:49 PM by Hooman »

Offline gpgarrettboast

  • Administrator
  • Hero Member
  • *****
  • Posts: 553
Outpost 2 DLL Programming
« Reply #2 on: April 09, 2004, 10:20:56 PM »
Here is the arguments for some commands

Code: [Select]
TethysGame::SetMeteor(Xpos,YPos,size)

Only one so far. I forgot the others, but I'll post them later.

Offline Arklon

  • Administrator
  • Hero Member
  • *****
  • Posts: 1267
Outpost 2 DLL Programming
« Reply #3 on: April 09, 2004, 11:11:20 PM »
Code: [Select]
TethysGame::SetInitialLight(value);

It was somewhere among those lines. It goes in InitProc().
« Last Edit: April 09, 2004, 11:13:19 PM by Arklon »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #4 on: April 10, 2004, 12:35:03 AM »
Woohoo. Thanks. I was looking for a function that would do that. Slight correction though.
Code: [Select]
	GameMap::SetInitialLightLevel(-96);
The parameter controls how far along the band of day and night is. Note that:
Code: [Select]
TethysGame::SetDaylightEverywhere(0);
must be used for the above to have any effect. I found the value of -96 would put the entire map (at least the one I was working on) into total darkness everywhere.  :whistle:  

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #5 on: April 11, 2004, 02:53:13 PM »
If that 0 referes to SetInitialLightLevel, then the effect of the value seems to depend on the map size. For the maps I tried, 0 put the band of daylight along the left edge of the map. On a smaller map, -96 put the band of daylight along the right edge while a value of -32 put that map into complete darkness. Hmm, I'd forgotten you'd already told me about his one.

As for the array, I've figured that for some time but I'm still unable to get the compiler to handle it properly. I've tried every which way I can think of but I either get a comile error, a link error, or it just doesn't resolve that import properly and crashes.

Oh, and the following creates a mining beacon. Some of the values were taken out of a DLL. I've noticed most positioning requires adding 31 to x and subtracting 1 from y to get the actual map coordinates. This seems to apply to the Disaster functions as well.
Code: [Select]
	TethysGame::CreateBeacon((map_id)0x51, xpos+31, ypos-1, 0, ?yield?, 0xFFFFFFFF);

 

Offline Cynex

  • Newbie
  • *
  • Posts: 31
Outpost 2 DLL Programming
« Reply #6 on: April 12, 2004, 07:03:10 PM »
Well, I've done lots of redifinitions in the current project.

Even if there is passed a TethysGame-var you can't determinate it, because it consists only of functions and therefore has no data stored at the referred address (which makes every offset possible).

For example you can define:
Code: [Select]
__declspec(dllexport) _cdecl int InitProc(TethysGame Game)
{
Game.CreateBeacon(map_Mining_Beacon, 0x41, 0x19, 0x0, 0x0, -1);
};
it'll work.

Furthermore it seems that classes actually consist of more than just functions.

Have seen the Player-Array?
It adds 0x0C to the original address, so one might assume that an index is 0x0C bytes.

just define three integers somewhere in the class _Player, preferred at the beginning:
Code: [Select]
	int unknown1, unknown2, unknown3;

This makes Player[1] work as (Player + 0x0C).
My current Player-declaration is:
Code: [Select]
_Player OP2 Player[6];

Also the LOCATION-struct seems to hold X and Y values:
Code: [Select]
	int x, y;
Put this at the beginning of the LOCATION-struct and it should work.

Furthermore the Unit-class contains the Unit-ID as I actually see it:
Code: [Select]
	int ID;
(Copy to the beginning of Unit-class)

This should make many function-calls possible.


If you disassemble one of the original dll's you might notice that there aren't any calls to Constructor-Procedures of the classes.
A Constructor takes initialising-values and stores theme somehow in the structure when defining a variable of a certain class or structure.

For the LOCATION-struct you will just add:
Code: [Select]
_inline LOCATION::LOCATION(int map_x, int map_y)
{
x = map_x;
y = map_y;
};
_inline LOCATION::LOCATION(void) { };

This eliminates unneeded extern calls (although it works with them).

For the Unit-class just add:
Code: [Select]
_inline Unit::Unit(void)
{
ID = 0;
};
(It is always set to 0 because there is no Unit yet.)

I use this function to test stuff:
Code: [Select]
__declspec(dllexport) _cdecl int InitProc(void)
{
Player[plr_1].GoEden();
Player[plr_1].SetColorNumber(0x00);
Player[plr_2].GoPlymouth();
Player[plr_2].SetColorNumber(0x01);

Unit RetUnit;
TethysGame::CreateUnit(RetUnit, map_ConVec, LOCATION(0x41, 0x19), plr_1, map_Default, 0);
RetUnit.SetCargo(map_Command_Center, map_Default);
//* RetUnit.DoBuild(RetUnit.GetCargo(), LOCATION(0x40, 0x20));
RetUnit.DoBuild(map_Command_Center, LOCATION(0x40, 0x20));
RetUnit.DoSetLights(1);

TethysGame::CreateUnit(RetUnit, map_Cargo_Truck, LOCATION(0x41, 0x18), plr_1, map_Default, 0);
RetUnit.SetTruckCargo(trck_Rare_Metal, 0);
RetUnit.SetDamage(30);
RetUnit.DoTransfer(plr_2);
// RetUnit.DoDeath();
// RetUnit.DoSelfDestruct();

Unit CargoTruck1 = RetUnit;

TethysGame::CreateUnit(RetUnit, map_Lynx, LOCATION(0x41, 0x1A), plr_1, map_RPG, 0);
RetUnit.SetWeapon(map_Microwave);
RetUnit.DoAttack(CargoTruck1);
// RetUnit.DoMove(LOCATION(0x20, 0x20));

Player[plr_1].CenterViewOn(0x41, 0x19);
Player[plr_1].SetFoodStored(3000);
Player[plr_1].SetKids(20);
Player[plr_1].SetWorkers(20);
Player[plr_1].SetScientists(15);

int RetTile = GameMap::GetTile(LOCATION(0x51, 0x13));
GameMap::InitialSetTile(LOCATION(0x41, 0x16), RetTile);
GameMap::SetTile(LOCATION(0x42, 0x17), RetTile);
GameMap::SetInitialLightLevel(0x40);

LOCATION TestLoc(0x10, 0x10);
TestLoc.Add(LOCATION(0x31, 0x01));
TethysGame::CreateUnit(RetUnit, map_Command_Center, TestLoc, plr_2, map_Default, 0);


TethysGame::ForceMoraleGreat(-1);
// TethysGame::ForceMoraleGood(-1);
// TethysGame::ForceMoraleOK(-1);
// TethysGame::ForceMoralePoor(-1);
// TethysGame::ForceMoraleRotten(-1);
TethysGame::SetDaylightMoves(1);
TethysGame::SetDaylightEverywhere(0);
TethysGame::SetCheatFastUnits(0);
TethysGame::SetCheatFastProduction(0);
TethysGame::SetCheatUnlimitedResources(0);
TethysGame::SetCheatProduceAll(0);

Player[plr_1].SetTechLevel(9);

TethysGame::CreateBeacon(map_Mining_Beacon, 0x41, 0x1B, beacon_rare, yield_3, -1);
TethysGame::CreateUnit(RetUnit, map_Mine, LOCATION(0x41, 0x1B), plr_1, map_Default, 0);

TethysGame::CreateWallOrTube(0x41, 0x1D, 0, map_Microbe_Wall);

return 1; // return 1 if OK; 0 on failure
};
(The commented functions are commented because it would make no sense to call them at these points - although they cause no error.)

I have problems calling GetCargo() and any other functions returning a value.
The exported functionname contains 'QBE' in outpost2.exe whereas C++ assumes 'QAE'.
Does anyone know how to declare it right?
I actaully use:
Code: [Select]
	map_id OP2 GetCargo(void);

Here a few tips how C++ exported symbols are decorated:
'AA' means that the specific argument is passed with an address-operator '&'
'PA' means the opposite: a pointer is passed '*'.
You can eliminate these decorations by deleting any '*' or '&' from the specific parameter.

There are many more - I don't wanna describe all (I don't even know all).


Appendix:

To make the above functions work you need some enum's.
I've declared the following:
Code: [Select]
enum map_id {
map_Default = 0,
map_Cargo_Truck,
map_ConVec,
map_Spider,
map_Scorpion,
map_Lynx,
map_Panther,
map_Tiger,
map_Robo_Surveyor,
map_Robo_Miner,
map_GeoCon,
map_Scout,
map_Robo_Dozer,
map_Evacuation_Transport,
map_Repair_Vehicle,
map_Earthworker,
map_Tube = 0x11,
map_Wall,
map_Lava_Wall,
map_Microbe_Wall,
map_Mine = 0x15,
map_Guard_Post = 0x17,
map_Light_Tower,
map_Common_Storage,
map_Rare_Storage,
map_Forum,
map_Command_Center,
map_MHD_Generator,
map_Residence,
map_Robot_Command,
map_Trade_Center,
map_Basic_Lab,
map_Medical_Center,
map_Nursury,
map_Solar_Power_Array,
map_Recreation_Facility,
map_University,
map_Agridome,
map_DIRT,
map_Garage,
map_Magma_Well,
map_Meteor_Defense,
map_Geothermal_Plant,
map_Arachnid_Factory,
map_Consumer_Factory,
map_Structure_Factory,
map_Vehicle_Factory,
map_Standard_Lab,
map_Advanced_Lab,
map_Observatory,
map_Reinforced_Residence,
map_Advanced_Residence,
map_Common_Ore_Smelter,
map_Spaceport,
map_Rare_Ore_Smelter,
map_GORF,
map_Tokamak,
map_Acid_Cloud = 0x3B,
map_EMP,
map_Laser,
map_Microwave,
map_Rail_Gun,
map_RPG,
map_Starflare,
map_Supernova,
map_ESG = 0x46,
map_Stickyfoam,
map_Thors_Hammer,
map_Mining_Beacon = 0x51
};
And:
Code: [Select]
enum Truck_Cargo {
trck_Empty = 0x00,
trck_Food,
trck_Common_Ore,
trck_Rare_Ore,
trck_Common_Metal,
trck_Rare_Metal,
trck_Common_Rubble = 0x06,
trck_Rare_Rubble,
trck_Spaceport = 0x08,
trck_Garbage = 0x09,
trck_Unit = 0x03F8
};
Also defined lots of constants:
Code: [Select]
// PlayerID's
#define plr_1 0
#define plr_2 1
#define plr_3 2
#define plr_4 3
#define plr_5 4
#define plr_6 5

// Mining beacon's
#define beacon_common 0
#define beacon_rare 1

// Yield Type's
#define yield_3 0
#define yield_2 1
#define yield_1 2

I've also given the parameters more meaningful names, but they're too much to post them all.
Here only the most important:
Code: [Select]
// TethysGame:
CreateBeacon(map_id BeaconType, int X, int Y, int Type, int Yield, int l3);
CreateUnit(Unit &ReturnUnit, map_id UnitType, LOCATION, int PlayerNum, map_id Weapon, int l9);
CreateWallOrTube(int X, int Y, int m5, map_id Type);

// GameMap:
CenterViewOn(int X, int Y);

// Unit:
SetCargo(map_id Cargo, map_id Default);
SetFactoryCargo(int Bay, map_id UnitType, map_id Default);
SetTruckCargo(Truck_Cargo Cargo, int Attrib);

That's all for now.
 

Offline Arklon

  • Administrator
  • Hero Member
  • *****
  • Posts: 1267
Outpost 2 DLL Programming
« Reply #7 on: April 17, 2004, 09:09:46 PM »
My unit value chart might help...

Also, you should figure out the code for making wreakage.
« Last Edit: April 17, 2004, 09:20:29 PM by Arklon »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #8 on: April 18, 2004, 02:22:14 AM »
DescBlock appears to be longer than 64 bits.

I'm currently using this:
#define COLONY 0xFFFFFFFF
#define TUTORIAL 0xFFFFFFFD

Code: [Select]
struct SDescBlock{
int type;
int unknown1;
int unknown2;
int unknown3;
};

SCRIPT_API SDescBlock DescBlock = { COLONY, 2, 0x0C, 0 };

If you don't properly initialize:
unknown1: You never have any available people even though you may have lots of people. Also, when you click on units, there controls appear but you really can't control them.
unknown2: You can't build anything at the structure factory
unknown3: You lose most of your menu controls

Also, I didn't notice any built in functions to lay down a line of tube or wall so I wrote this one:

Code: [Select]
// Create a line of wall or tube 
// Draw along the horizontal first:
//  If coordinates represent a bent wall/tube then draw
//  horizontal between x1 and x2 (along y1) and then
//  vertical between y1 and y2 (along x2)
void CreateTubeOrWallLine(int x1, int y1, int x2, int y2, map_id type)
{
int i;
int vert;
int horz;

// Adjust coordinates for odities of the game
x1 += 31; x2 += 31;
y1 -= 1; y2 -=1;

// Determine which edges to draw along
vert = x2;
horz = y1;

// Make sure (x1 < x2) and (y1 < y2)
if (x1 > x2){ x1 ^= x2; x2 ^= x1; x1 ^= x2; }
if (y1 > y2){ y1 ^= y2; y2 ^= y1; y1 ^= y2; }

// Create horizontal section
for (i = x1; i <= x2; i++)
  TethysGame::CreateWallOrTube(i, horz, 0, type);
// Create vertical section
for (i = y1; i <= y2; i++)
  TethysGame::CreateWallOrTube(vert, i, 0, type);
}

Enjoy.

Also, I found that by going through the steps to build the import library myself, I managed to solve a lot of other problems. For instance, linking CreateUnit and being able to properly use Player as an array. Hmm, could have been a compiler/linker version difference I guess. Repeated from op2hacker's post, the steps can be found here: http://support.microsoft.com/default.aspx?...&NoWebContent=1

Arklon, thank you so much for that chart. Anyone have one for the techs? And Cynex, wow! Thanks.

Edit: Hey Cynex, this seems to be what you are looking for. The B in "?Workers@_Player@@QBEHXZ" seems to mean const. That is, the functions should be declared as:
   
Code: [Select]
int Workers() const;
« Last Edit: April 18, 2004, 03:43:57 AM by Hooman »

Offline Arklon

  • Administrator
  • Hero Member
  • *****
  • Posts: 1267
Outpost 2 DLL Programming
« Reply #9 on: April 18, 2004, 09:19:40 AM »
I believe techs are identified through ID's (consists of several numbers). The only way to get these ID's is from sheets.vol.

I got the tech ID's from the demo. With any luck, they didn't changed the order of these ID's. However, the names are a bit different.

Code: [Select]
;  02101 Agridome
;  02103 Command Center
;  02104 Structure Factory
;  02106 Basic Laboratory
;  02107 Light Tower
;  02108 Common Ore Mine
;  02109 Residence
;  02110 Common Ore Smelter
;  02111 Common Metals Storage Tanks
;  02112 Tokamak
;  02114 Tube
;  02115 Trade Center
;  03101 Standard Lab
;  03301 DIRT
;  03302 GORF
;  03303 Medical Center
;  03304 Nursery
;  03305 University
;  03501 Robot Command Center
;  03502 Vehicle Factory
;  03601 Scout
;  03602 Laser Turret
;  03603 Microwave Turret
;  03604 Cargo Truck
;  03605 Construction Vehicle
;  03606 Earthworks Constructor
;  03607 Evacuation Transport
;  03608 Robo-Dozer
;  03609 Robo-Miner
;  03610 Robo-Surveyor
;  03801 Guard Post
;  03851 Light Combat Chassis
;  05101 Consumer Goods Factory
;  05102 Garage
;  05104 Advanced Lab
;  05105 Recreation Facility
;  05106 Walls, Concrete
;  05107 ASE Converter (MHD Generator, I believe)
;  05108 Forum
;  05110 Rare Ore Mine
;  05115 Geothermal Constructor
;  05116 Factory, Arachnid and Spider
;  05201 Medium Combat Chassis
;  05202 StickyFoam Turret
;  05301 Earthquake Prediction
;  05302 Electrical Storm Prediction
;  05303 Vortex Prediction
;  05304 Volcanic Eruption Prediction
;  05401 Repair Vehicle
;  05501 Rare Ore Smelter
;  05502 Rare Metals Storage Tanks
;  05503 SULV
;  05504 EDWARD Satellite
;  05506 Rail Gun Turret
;  05508 EMP Turret
;  05602 Cannon Turret (RPG, I believe)
;  07102 Starflare Turret
;  07103 ESG Turret
;  07104 Scorpion
;  08051 Observatory
;  08102 Lava Wall
;  08103 Magma Well
;  08104 Advanced Residence
;  08105 Reinforced Residence
;  08106 Meteor Defense
;  08201 Heavy Combat Chassis
;  08203 Supernova Turret
;  08317 Volcanic Eruption Prediction
;  08401 Microbe Wall
;  08503 Corrosive Acid Turret (Acid Cloud)
;  08601 Orbital Space Station (Skydock)
;  08801 Starship Superstructure I (?)
;  08901 Starship Superstructure II (?)
;  10101 RLV
;  10102 Thor's Hammer Turret
;  10202 Ship's Computer (Command Module)
;  10203 Ship's Propulsion System (I think Ion Drive or Fusion Drive)
;  10204 Solar Power Satellite & Array
;  10205 Starship Hull and Shielding (Maybe habitat ring?)
;  10206 Starship Long-Range Sensors (Sensor package?)
;  10207 Starship Superstructure III (?)
;  10208 Suspended animation (Stasis Systems)
;  10209 Starship Short-Range Sensors (Sensor package?)
;  10401 Ship's Power Distribution System (Ion Drive or Fusion Drive)
;  12201 EMP Missiles
« Last Edit: April 18, 2004, 01:38:51 PM by Arklon »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #10 on: April 18, 2004, 01:39:33 PM »
Cool, Thanks. They seem to work. I tried a few of them. The following lets you build rail guns right at the start of the game:
Code: [Select]
	Player[0].MarkResearchComplete(3801);
Player[0].MarkResearchComplete(5506);

I've got a few triggers going.

Code: [Select]
	Trigger trig;
trig = CreateTimeTrigger(1, 1, 101, "NoResponseToTrigger");
trig = CreateTimeTrigger(1, 1, 301, "NoResponseToTrigger");
trig = CreateTimeTrigger(1, 1, 501, "NoResponseToTrigger");
trig = CreateTimeTrigger(1, 1, 701, "NoResponseToTrigger");
trig = CreateTimeTrigger(1, 1, 901, "NoResponseToTrigger");
//trig = CreateEvacTrigger(1, 1, 1, "NoResponseToTrigger");
CreateVictoryCondition(1, 1, trig, "Text that appears in objective list");
//CreateFailureCondition(1, 1, trig, "Not sure what this is for");
The third parameter is the time at which the trigger fires relative to the current time (when the trigger is setup). Each time mark is 100 units. So 100 is still time mark 0 but 101 is the start of time mark 1 which lasts until 200. The Victory and Failure conditions work.

I tried putting the follow in NoResponseToTrigger (which I guess is a response  :lol: ):
   
Code: [Select]
char buffer[64];
scr_snprintf(buffer, 64, "Opponents Workers: %d", Player[1].Workers());
TethysGame::AddMessage(-1,-1,buffer,0,0);
The output appears in your list of messages. Interestingly enough, the computer always has 4096 workers no matter what you try to set it to. If you you Player.GoHuman() then the number of workers is set properly but as soon as you use Player.GoAI() it sets it to 4096 and can't be changed from that. The -1, -1 in AddMessage causes the message to not be associated with a particular area of the map (No "JumpTo" option for this message). I haven't been able to move to focus away from the top left corner of the map so it doesn't seem like these are x and y coordinates. The 64 in scr_snprintf I believe is the length of your buffer. It doesn't seem to print beyond that many characters into the buffer. It works pretty much exactly like sprintf/(fprintf) in C.
« Last Edit: April 18, 2004, 01:50:20 PM by Hooman »

Offline Cynex

  • Newbie
  • *
  • Posts: 31
Outpost 2 DLL Programming
« Reply #11 on: April 18, 2004, 01:46:47 PM »
Thanks @Hooman, however it doesn't solve the problem.

Here are the errors it gives me:
Code: [Select]
// My old call:
enum map_id __thiscall Unit::GetCargo(void)" (__imp_?GetCargo@Unit@@QAE?AW4map_id@@XZ)

// The const-version:
enum map_id const __thiscall Unit::GetCargo(void)" (__imp_?GetCargo@Unit@@QAE?BW4map_id@@XZ)
So you was right - it changed an 'A' into a 'B', but the wrong.

The Name as it should be:
Code: [Select]
?GetCargo@Unit@@QBE?AW4map_id@@XZ

I can work around this problem by editing the obj-file in a hexeditor manually, but this isn't the method anybody prefers.

Also thanks for the CreateWallOrTubeLine()-function (I've renamed it this way to not mix up with the names).
It helps a lot, however I don't see why to adjust the coordinates (+31/-1). The whole game works with them and in my opinion it actually confuses more than it helps.


To come to few new things:

Note: I ever use 'tutorial.map' for testing.

Here is how I currently think the DescBlock works:

Code: [Select]
struct SDescBlock
{
int ID, unknown2, unknown3, unknown4;
char *MAPNAME, *TECHTREE, *LEVELDESC;
int unknown8;
};

SCRIPT_API SDescBlock DescBlock = {-3, 2, 12, 0, MapName, TechtreeName, LevelDesc, 0};

I only know few IDs:
-3 = Tutorial
-1 = Colony-game or demo
All values above 0 for campaign-missions.
More values below 0 seem to be used for various kinds of multiplayer-missions.

The 4th value seems to be used in non-colony missions in which you only control vehicles and therefore most controls are disabled by setting this value true.


Also I've just discovered how CreateUnitBlock() and some Triggers work:

CreateUnitBlock()

The call is quite simple:
Code: [Select]
// TethysGame:
static int __fastcall CreateUnitBlock(_Player &Player, char const *BlockName, int m2);

Use this for testing-purposes:
Code: [Select]
	TethysGame::CreateUnitBlock(Player[plr_1], "Units\0", 0);
Where "Units" is the name of an exported Record.

The Record will be defined like follows:
Code: [Select]
SCRIPT_API UnitBlock Units(UnitRec);
('Units' is the above referred name, 'UnitRec' is a Unit-Record taken for initialisation)

I've created the following to test most values: (Also useful to test triggers)
Code: [Select]
UnitRecord UnitRec[] = {
{map_Vehicle_Factory, 0x30, 0x10, 0, 0, map_Default, 0x10, 0, 0},
{map_Structure_Factory, 0x30, 0x14, 0, 0, map_Default, 0x10, 0, 0},
{map_Command_Center, 0x30, 0x17, 0, 0, map_Default, 0x10, 0, 0},
{map_Common_Ore_Smelter,0x30, 0x1A, 0, 0, map_Default, 0x10, 0, 0},
{map_Rare_Ore_Smelter, 0x30, 0x1E, 0, 0, map_Default, 0x10, 0, 0},
{map_Tokamak,   0x23, 0x03, 0, 0, map_Default, 0x10, 0, 0},
{map_ConVec,   0x32, 0x14, 0, 0, map_Default, 0x10, 0, 0},
{map_Cargo_Truck,  0x34, 0x10, 0, 0, map_Default, 0x10, trck_Rare_Metal, 1000},
{map_Tiger,    0x34, 0x17, 0, 0, map_Thors_Hammer, 0x10, 0, 0},
{map_Default,   0,  0,  0, 0, map_Default, 0,  0, 0}
};

Needs:
Code: [Select]
struct UnitRecord {
map_id Type;
int X, Y;
int unknown1, unknown2;
map_id Weapon;
int unknown3;
short Cargo;
short Attrib;
};
This is all to make CreateUnitBlock() work.
Note: The declaration only works when including the CRT (which should be by default).
(I've excluded CRT to make the dll smaller, but then discovered it doesn't work.)


Triggers

Just start with some enums:
Code: [Select]
enum compare_mode {
cmp_Default = 0,
cmp_Equal = 0,
cmp_Lower_Equal,
cmp_Greater_Equal,
cmp_Lower = 3,
cmp_Greater = 4
};
enum trig_res {
res_common_ore = 0x01,
res_rare_ore
};
Declarations:
Code: [Select]
// Global Functions
Trigger OP2 __fastcall CreateTimeTrigger(int Enable, int BoolNoRepeat, int TMin, int TMax, char const *TriggerFunc);
Trigger OP2 __fastcall CreateTimeTrigger(int Enable, int BoolNoRepeat, int Time100, char const *TriggerFunc);
Trigger OP2 __fastcall CreateVehicleCountTrigger(int Enable, int BoolNoRepeat, int PlayerNum, int RefCount, compare_mode, char const *TriggerFunc);
Trigger OP2 __fastcall CreateBuildingCountTrigger(int Enable, int BoolNoRepeat, int PlayerNum, int RefCount, compare_mode, char const *TriggerFunc);
Trigger OP2 __fastcall CreateResourceTrigger(int Enable, int BoolNoRepeat, trig_res, int RefAmount, int PlayerNum, compare_mode, char const *TriggerFunc);
Trigger OP2 __fastcall CreateVictoryCondition(int Enable, int dd6, Trigger &, char const *ConditionText);
And a new player-constant as I guess it:
Code: [Select]
	// PlayerID's
#define plr_all -1

Add this to InitProc: (best at the end)
Code: [Select]
	Trigger TTrig = CreateTimeTrigger(0, 1, 1, "NoResponseToTrigger\0");
Trigger RetTrig;
// RetTrig = CreateVictoryCondition(0, 1, TTrig, "Test-Condition 1.");

// TTrig = CreateTimeTrigger(1, 1, 200, "TestTrigger\0");
TTrig = CreateTimeTrigger(1, 1, 100, 1000, "TestTrigger\0");
// TTrig.Enable();

TTrig = CreateVehicleCountTrigger(1, 0, plr_1, 0x4, cmp_Lower_Equal, "TestTrigger2\0");

TTrig = CreateResourceTrigger(1, 1, res_rare_ore, 500, plr_all, cmp_Greater, "TestTrigger2\0");

// TTrig = CreateTimeTrigger(1, 1, 100, "NoResponseToTrigger\0");
RetTrig = CreateVictoryCondition(1, 1, TTrig, "Test-Condition 3.");

TTrig = CreateBuildingCountTrigger(1, 1, plr_1, 0x7, cmp_Greater, "TestTrigger2");
And the following exported functions:
Code: [Select]
SCRIPT_API void TestTrigger(void)
{
Unit RetUnit;
TethysGame::CreateUnit(RetUnit, map_Tiger, LOCATION(0x21, 0x01), plr_1, map_RPG, 0);
};
SCRIPT_API void TestTrigger2(void)
{
Unit RetUnit;
TethysGame::CreateUnit(RetUnit, map_Tiger, LOCATION(0x27, 0x07), plr_1, map_Acid_Cloud, 0);
};
I think the functions are self-explaining since i give the examples.

A note concerning the CreateTimeTrigger()-procedure:
if you pass 5 parameters, the game will take the third and the forth, and randomly select a time between these marks to execute the trigger-function.

Note2: You may just discover that a time of 100 means one mark in the game.

Triggers as well as VictoryConditions have an Enabled-Switch.
Only with this switch activated (usually first parameter) they'll have effect.


The current .def-file I use:
Code: [Select]
LIBRARY t15
EXPORTS
AIProc               @1
DescBlock            @2
GetSaveRegions       @3
InitProc             @4
LevelDesc            @5
MapName              @6
NoResponseToTrigger  @7
StatusProc           @8
TechtreeName         @9
TestTrigger          @10
TestTrigger2         @11
(You only need to list exported functions here (not variables) )
 

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #12 on: April 18, 2004, 01:58:41 PM »
You need to declare this:

Code: [Select]
	map_id GetCargo() const;

The const at the end means that the functions does not modify any local variables and hence can be called when your instance of the class is a constant. Putting the const at the beginning makes the return value a constsant. I just tried it and it compiled fine.

 

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #13 on: April 19, 2004, 12:54:53 AM »
Update to the map_id enum. I've added Magma Vents and Fumaroles.

Code: [Select]
	map_Mining_Beacon = 0x51,
map_Magma_Vent,
map_Fumarole

Here is some code to place such things

Code: [Select]
	// Create common ore beacons
TethysGame::CreateBeacon(map_Mining_Beacon, x-28, y-21, beacon_common, yield_3, 0);
TethysGame::CreateBeacon(map_Mining_Beacon, x-25, y+7, beacon_common, yield_3, 0);
// Create rare ore beacons
TethysGame::CreateBeacon(map_Mining_Beacon, x+17, y+31, beacon_rare, yield_3, 0);

// Create magma wells
TethysGame::CreateBeacon(map_Magma_Vent, x-25, y+40, -1, -1, -1);

// Create fumaroles
TethysGame::CreateBeacon(map_Fumarole, x+1, y-24, -1, -1, -1);
TethysGame::CreateBeacon(map_Fumarole, x-5, y+38, -1, -1, -1);

Oh, and a really minor point, but I think LevelDesc and TechtreeName in the SDescBlock are backwards.

I tried using the PlayerVehicleEnum class. Couldn't think of much to do with it but to turn on the headlights of all the vehicles for a given player. It seemed kinda convenient at the time.

Code: [Select]
// Note: CAN NOT use playerNum = -1 for all players
void SetAllVehicleLightsForPlayer(int playerNum, int bOn)
{
PlayerVehicleEnum unitEnum(playerNum); // Enumerate vehicles for given player
Unit curUnit;

// Enumerate through all vehicles of this player
while (unitEnum.GetNext(curUnit))
{
  curUnit.DoSetLights(bOn); // Turn on the headlights
}
}

The updated class is

Code: [Select]
class OP2 PlayerVehicleEnum {
public:
// GetNext: If there are units left to enumerate, copies current
//   unit into curUnit and returns 1, otherwise it returns 0
int GetNext(Unit &curUnit);
PlayerVehicleEnum(int playerNum);
};

It looks like PlayerBuildingEnum and PlayerUnitEnum work the same way. Note: "Unit" encompases both Vehicles and Buildings.
 

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #14 on: April 19, 2004, 08:41:19 PM »
Well, I've got a bit of a clone going for the Eden Colony Starship level. It stills needs Failure Conditions but here are the Victory Conditions

Code: [Select]
	// Create victory conditions for - Colony, Starship
trig = CreateCountTrigger(1, 1, -1, map_Evacuation_Module, (map_id)-1, 1, cmp_Greater_Equal, "NoResponseToTrigger");
CreateVictoryCondition(1, 1, trig, "Evacuate 200 colonists to spacecraft");
trig = CreateCountTrigger(1, 1, -1, map_Food_Cargo, (map_id)-1, 1, cmp_Greater_Equal, "NoResponseToTrigger");
CreateVictoryCondition(1, 1, trig, "Evacuate 10000 units of food to spacecraft");
trig = CreateCountTrigger(1, 1, -1, map_Common_Metals_Cargo, (map_id)-1, 1, cmp_Greater_Equal, "NoResponseToTrigger");
CreateVictoryCondition(1, 1, trig, "Evacuate 10000 units of Commom Metals to spacecraft");
trig = CreateCountTrigger(1, 1, -1, map_Rare_Metals_Cargo, (map_id)-1, 1, cmp_Greater_Equal, "NoResponseToTrigger");
CreateVictoryCondition(1, 1, trig, "Evacuate 10000 units of Rare Metals to spacecraft");

The parameters match exactly what I found in the regular DLL. I added a few more things to the map_id enum.

Code: [Select]
	map_Disasterous_Building_Explosion = 0x55,
map_Catastrophic_Building_Explosion,
map_Athiest_Building_Explosion,

map_EDWARD_Satellite = 0x58,
map_Solar_Satellite,
map_Ion_Drive_Module,
map_Fusion_Drive_Module,
map_Command_Module,
map_Fueling_Systems,
map_Habitat_Ring,
map_Sensor_Package,
map_Skydock,
map_Stasis_Systems,
map_Orbital_Package,
map_Pheonix_Module,

map_Rare_Metals_Cargo,
map_Common_Metals_Cargo,
map_Food_Cargo,
map_Evacuation_Module,
map_Children_Module,

map_SULV,
map_RLV,
map_EMP_Missile,

map_Impulse_Items = 0x6C,
map_Wares,
map_Luxury_Wares,

map_Inter_Colony_Shuttle = 0x6F,
map_Spider_3_Pack,
map_Scorpion_3_Pack,

map_Pretty_Art = 0x72

I got the names by seeing what I could put into the bay of a starport. It took me a while to realize I'd already seen all these in Arklon's unit value chart. Well, consider them double checked.  :blush:

Here is the code I used for the Startport and the items in the bays
Code: [Select]
TethysGame::CreateUnit(retUnit, map_Spaceport, LOCATION(x-8, y-1), playerNum, map_Default, 0);
retUnit.SetFactoryCargo(-1, map_RLV, map_Default); // Note: Any bay number will place this on the launch pad
retUnit.SetFactoryCargo(0, map_Common_Metals_Cargo, map_Default);
retUnit.SetFactoryCargo(1, map_Rare_Metals_Cargo, map_Default);
retUnit.SetFactoryCargo(2, map_Food_Cargo, map_Default);
retUnit.SetFactoryCargo(3, map_Evacuation_Module, map_Default);
retUnit.SetFactoryCargo(4, map_EDWARD_Satellite, map_Default);
retUnit.SetFactoryCargo(5, map_Solar_Satellite, map_Default);

Oh, and I haven't had to use the CRT yet. I had it complain a little while ago about wWinMain@16 but I disabled Exception handling and it went away. I did this in Project->Settings->C/C++->C++ Language.

Hmm. For some reason all my calls to create natural disasters aren't doing anything right now. I know they used to work for me.
« Last Edit: April 19, 2004, 09:45:27 PM by Hooman »

Offline gpgarrettboast

  • Administrator
  • Hero Member
  • *****
  • Posts: 553
Outpost 2 DLL Programming
« Reply #15 on: April 20, 2004, 07:56:03 AM »
I can't seem to find out how to set the disasters to what mark I want them to occur at.  Does anyone know how to do that? All of the disasters I set occur at mark 10...  Thanks.

Offline BlackBox

  • Administrator
  • Hero Member
  • *****
  • Posts: 3093
Outpost 2 DLL Programming
« Reply #16 on: April 20, 2004, 02:27:09 PM »
You have to create a time trigger, and put the disaster set function in the trigger callback.

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #17 on: April 20, 2004, 03:58:32 PM »
I've only gotten a Vortex to appear right away.

Code: [Select]
	//TethysGame::SetTornado(loc.x, loc.y, duration, 1, 1, 1);

I think the reason why is that most disasters give you a warning about when they are going to happen (provided you did the research). Thus, there is a delay of about 10 time marks before the disaster actually appears. If you change the last few parameters in the above code, then there is a delay as well. I think those parameters may have been added so they could create that Vortex right away in one of the demo games that appears if you do nothing at the main menu. Most of the disasters don't have that many parameters. Lightning storms can probably be used the same way.

Oh, and I had to add a few unknowns to the PlayerBuildingEnum class to get it to work right. I've currently got this:

Code: [Select]
class OP2 PlayerBuildingEnum {
public:
int GetNext(Unit &curUnit);
PlayerBuildingEnum(int playerNum, map_id buildingType);

int unknown1, unknown2;
};

I haven't tested it all that much but I'm pretty sure that what all the parameters mean.

I suppose I should also mention that we should figure out how much data each of the classes hold so that when we create them, they don't corrupt the stack. Even if they don't write to certain locations in their constructor, they may try to write elsewhere in the function calls and I think that's why I had some funny stuff happen with PlayerBuildingEnum.

Well, here's an example of how to use the above. I put this into a trigger that fires about every half a time mark.  :whistle:

Code: [Select]
	Unit curUnit;
LOCATION loc(0, 0);

// Find a player building
if (enumBuilding.GetNext(curUnit))
{
  loc = curUnit.Location();// Get the coordinates of the building
  TethysGame::SetMeteor(loc.x, loc.y, 500); // Send a big rock at it ;>
}
else
{
enumBuilding = PlayerBuildingEnum(0, map_Default);
}

Note that the class was declared globally in this example.

Code: [Select]
PlayerBuildingEnum enumBuilding(0, map_Default); // All buildings
or
Code: [Select]
PlayerBuildingEnum enumBuilding(0, map_Command_Center); // Just the command centers

 

Offline Cynex

  • Newbie
  • *
  • Posts: 31
Outpost 2 DLL Programming
« Reply #18 on: April 20, 2004, 05:24:59 PM »
I exclude the CRT by enabling 'ignore all default libraries' in the Linker-setup.
This causes problems when initialising global variables with a constructor (which has to be called when loading.)
For example 'UnitBlock' doesn't load.

There are maybe possibilities to work around it.


Currently I try to understand groups:

They only seem to be available for KI-Players.
Units within a group can do certain tasks automatically, like searching for enemy-units and destroying them ;)

The most general type may be 'ScGroup':

Code: [Select]
class ScGroup {
public:
int PlayerKI;
void AddUnits(UnitBlock &AddUnits);
int GetFirstOfType(Unit &ReturnUnit, UnitClassifactions);
int GetFirstOfType(Unit &ReturnUnit, map_id Type, map_id Weapon);
void RemoveUnit(Unit);
ScGroup(void);
void SetLights(int BoolOn);
void TakeUnit(Unit);
int TotalUnitCount(void);
int UnitCount(UnitClassifactions);
~ScGroup(void);
};
(Note: I've only included the functions I understood so far, the others didn't change)

The following enum isn't yet completed, but hope it'll help:
Code: [Select]
enum UnitClassifactions {
cls_Attack = 0,
cls_ESG,
cls_EMP,
cls_Stickyfoam,
cls_Convecs = 5,
cls_Cargo_Trucks = 7,
cls_Earthworkers = 8,
cls_Robo_Dozers = 9,
cls_test = 4 // No special need
};
Explaination of cls_Attack:
All vehicles or even buildings which have one of the following weapons:
Microwave
Laser
Rail Gun
Starflare
Supernova
RPG
Acid Cloud
Thor's Hammer
Energy Cannon (Scorpions)

The rest should be clear.

Use this for testing:
Code: [Select]
	TethysGame::CreateUnit(RetUnit, map_Tiger, LOCATION(0x41, 0x1B), plr_2, map_EMP, 0);
// TethysGame::CreateUnit(RetUnit, map_Scout, LOCATION(0x41, 0x1B), plr_2, map_Default, 0);
ScGroup UBGroup;
UBGroup.PlayerKI = 0; // obviously must be PlayerNum -1 of all included units
// UBGroup.AddUnits(Units);
UBGroup.TakeUnit(RetUnit); // Adds Unit to the group
UBGroup.SetLights(1);
UBGroup.GetFirstOfType(RetUnit, map_Tiger, map_EMP);
//UBGroup.RemoveUnit(RetUnit); // Removes Unit from group but not from game
//RetUnit.DoSelfDestruct();

char buffer[64];
scr_snprintf(buffer, 64, "Unit Count: %d", UBGroup.UnitCount(cls_Defense));
TethysGame::AddMessage(-1, -1, buffer, 0, 0);

Other Groups may work similar and they even have a Create-function which sets up the group for a specified Player:
Code: [Select]
BuildingGroup OP2 __fastcall CreateBuildingGroup(_Player);
FightGroup OP2 __fastcall CreateFightGroup(_Player);
MiningGroup OP2 __fastcall CreateMiningGroup(_Player);
Either they've made the Create-function for ScGroup inline or there is no one needed (setting PlayerKI suffices to make it work).


Oh - just noticed that there's a weapon I forgot:
Code: [Select]
	map_Energy_Cannon, // (Scorpion)
Add this directly behind map_Thors_Hammer.
 

Offline Cynex

  • Newbie
  • *
  • Posts: 31
Outpost 2 DLL Programming
« Reply #19 on: April 21, 2004, 04:19:49 PM »
The following is a complete list of the research-topics available through 'multitek.txt'.

Note:
In this tech there are different topics for Eden and Plymouth in some cases.
For all missions (edentek.txt or ply_tek.txt) only use Topics marked with Eden in this list, when they are available for Plymouth too.

For example in multiplayer the following topics are available:
05051 = Robot-Assist Mechanic (Eden)
05052 = Robot-Assist Mechanic (Plymouth)
In both Eden and Plymouth missions using edentek or ply_tek you'll only use 05051.
However in multiplayer games you have to distinguish between Eden and Ply.


===========================================================================
02099 = Spider
02101 = Agridome
02103 = Command Center
02104 = Structure Factory
02107 = Light Tower
02108 = Common Ore Mine
02109 = Residence
02110 = Common Ore Smelter
02111 = Common Metals Storage Tanks
02112 = Tokamak
02114 = Tube
02115 = Trade Center
03101 = Standard Lab
03201 = Seismology
03202 = Vulcanology
03301 = Emergency Response Systems
03302 = Metals Reclamation
03303 = Health Maintenance
03304 = Offspring Enhancement
03305 = Research Training Programs
03306 = Leisure Studies
03401 = Cybernetic Teleoperation
03402 = High-Temperature Superconductivity
03403 = Hydroponic Growing Media
03405 = Metallogeny
03406 = Environmental Psychology
03407 = Large-Scale Optical Resonators
03408 = Focused Microwave Projection
03501 = 03501 Robot Command Center
03502 = 03502 Vehicle Factory
03601 = 03601 Scout
03602 = Laser Turret
03603 = Microwave Turret
03604 = Cargo Truck
03605 = Construction Vehicle
03606 = Earthworks Constructor
03608 = Robo-Dozer
03609 = Robo-Miner
03610 = Robo-Surveyor
03801 = Guard Post
03851 = Mobile Weapons Platform
03901 = Advanced Vehicle Power Plant
05051 = Robot-Assist Mechanic (Eden)
05052 = Robot-Assist Mechanic (Plymouth)
05101 = Consumerism
05102 = Garage
05104 = Lab, Advanced
05106 = Walls, Concrete
05107 = Magnetohydrodynamics
05108 = Public Performance
05110 = Rare Ore Processing
05111 = Independent Turret Power Systems
05115 = Geothermal Power
05116 = Legged Robots
05201 = Advanced Combat Chassis
05202 = Dissipating Adhesives
05302 = Meteorology
05303 = Severe Atmospheric Disturbances
05305 = DIRT Procedural Review
05306 = Recycler Postprocessing
05307 = Automated Diagnostic Examinations
05309 = Hypnopaedia (Eden)
05310 = Hypnopaedia (Plymouth)
05317 = Reinforced Vehicle Construction
05318 = Robotic Image Processing
05401 = Repair vehicle
05405 = Space Program
05408 = Forum Reconfiguration
05501 = Smelter, Rare Ore construction
05502 = Storage Tanks, Rare Metals
05503 = SULV
05504 = EDWARD satellite
05506 = Directional Magnetic Fields
05508 = Electromagnetic Pulsing
05599 = Rocket Propulsion
05601 = Heat Dissipation Systems (Plymouth)
05602 = Rocket Launcher
05701 = Lava Defenses
07102 = Explosive Charges
07103 = Multiple Mine Projectile System
07104 = Arachnid Weaponry
07201 = Rare Ore Extraction
07202 = Hot-Cracking Column Efficiency
07203 = Smelter Postprocessing
07206 = Scout-class Drive Train Refit
07211 = Extended-Range Projectile Launcher (Eden)
07212 = Extended-Range Projectile Launcher (Plymouth)
07213 = Advanced Robotic Manipulator Arm (Eden)
07214 = Advanced Robotic Manipulator Arm (Plymouth)
07403 = Increased Capacitance Circuitry
07405 = Scorpion Power Systems
08049 = Meteor-Watch Observatory
08051 = Observatory
08103 = Magma Refining
08104 = Expanded Housing
08105 = Disaster-Resistant Housing
08106 = High-Energy Ray-Composite Projector
08201 = Dual-Turret Weapons Systems
08203 = High-Powered Explosives
08301 = Efficiency Engineering (Eden)
08302 = Efficiency Engineering (Plymouth)
08304 = Heat Mining
08306 = Enhanced Defensive Fortifications
08307 = Multitainment Console Upgrade
08309 = Reinforced Panther Construction
08316 = Meteor Detection
08317 = Meteor detection
08319 = Spider Maintenance Software Revision
08320 = Reduced Foam Evaporation
08321 = Arachnid Durability
08503 = Acid Weaponry
08601 = Skydock
08801 = Ion Drive Module
08901 = Fusion Drive Module
08951 = Fueling Systems
10101 = Improved Launch Vehicle
10102 = Artificial Lightning
10202 = Command Module
10204 = Solar Power
10205 = Habitat Ring
10206 = Sensor Package
10208 = Stasis Systems
10209 = Orbital Package
10301 = Magma Purity Control
10303 = Advanced Armoring Systems
10305 = Grenade Loading Mechanism (Eden)
10306 = Grenade Loading Mechanism (Plymouth)
10309 = Precision Trajectory Projection Software
10401 = Phoenix Module
11999 = Tiger Speed Modification
12101 = Heat Dissipation Systems (Eden)
12201 = Rocket Atmospheric Re-entry System
12599 = Evacuation Module

// Unavailable Technologies
02106 = Basic Laboratory
03607 = Evacuation Transport
08401 = Microbe Wall
12499 = Children's Module
===========================================================================

This is how to use the IDs:

Code: [Select]
class _Player {
public:
int OP2 canDoResearch(int decResearchID);
int OP2 HasTechnology(int decResearchID) const;
void OP2 MarkResearchComplete(int decResearchID);
void OP2 SetTechLevel(int TechLevel);
};

Note considering techlevels:
Although I didn't test it, it seems that the first two decimal digits of each research topic are the techlevels.
Therefore if you call
Code: [Select]
	Player[plr_1].SetTechLevel(9);
all Technologies with 09XXX might be available.
« Last Edit: April 24, 2004, 03:27:45 PM by Cynex »

Offline Cynex

  • Newbie
  • *
  • Posts: 31
Outpost 2 DLL Programming
« Reply #20 on: April 24, 2004, 02:19:27 PM »
canDoResearch(int decResearchID)
Returns true if player has done all researches to do the specified research.

HasTechnology(int decResearchID) const
Returns whether the player has completed the specified research yet.

MarkResearchComplete(int decResearchID)
Marks a research as done.

SetTechLevel(int TechLevel)
Sets a whole couple of researches done.
 

Offline Cynex

  • Newbie
  • *
  • Posts: 31
Outpost 2 DLL Programming
« Reply #21 on: April 24, 2004, 03:26:38 PM »
Quote
There's two "Heat Dissipation Systems" research things on your list. You didn't mark them as Eden or Plymouth...
Oh - I must have overlooked that.

Seems Plymouth can do it far earlier than Eden:

05601 = Heat Dissipation Systems (Plymouth)
12101 = Heat Dissipation Systems (Eden)

I'll edit that.

edit - note:
In Plymouth-missions use 05601, in Eden and tutorials 12101.
« Last Edit: April 24, 2004, 03:31:14 PM by Cynex »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #22 on: June 25, 2004, 06:25:01 PM »
Here is how to start a virus:

Code: [Select]
	GameMap::SetVirusUL(LOCATION(locX,locY), 1);
TethysGame::SetMicrobeSpreadSpeed(0xa0);

Interesting note: When I did this in a colony game, it only seemed to spread on bulldozed terrain.

Well, I guess it could make for an interesting multiplayer game. See who's blight walls fail first.  :lol: You could kill each other by attacking their walls or bulldozing their base.  

Offline Kramy

  • Full Member
  • ***
  • Posts: 173
Outpost 2 DLL Programming
« Reply #23 on: June 29, 2004, 06:00:57 PM »
Here's an update to Hooman's template, which he said I should post here. :) First are mission-type defines, then an updated starting resources function for different difficulties, then I changed Hooman's create-tube function so that if you HAVE to make tube vertical(or horizontal) it's easier.(just add "true" as a last parameter and it's the same as before)

/ ---------------------------------------------- //

// Dll Names (begin with)
// a = "autodemo"(op2 idle)
// c = ColonyMission
// mu = Multiplayer-Landrush
// mf = Multiplayer-Spacerace
// mr = Multiplayer-ResourceRace
// mm = Multiplayer-Midas
// ml = Multiplayer-LastOne

// missionType defines (Grabbed with hex editor from OP2's Dlls)
#define COLONY 0xFFFFFFFF
#define TUTORIAL 0xFFFFFFFD
#define MULTI_LR 0xFFFFFFFC
#define MULTI_SR 0xFFFFFFFB
#define MULTI_RR 0xFFFFFFFA
#define MULTI_MI 0xFFFFFFF9
#define MULTI_LO 0xFFFFFFF8

// ---------------------------------------------- //

void InitializePlayerResources(_Player &player)
{
// Easy
if(player.Difficulty() == 0)
{
player.SetOre(6000);
player.SetFoodStored(3000);
player.SetWorkers(30);
player.SetScientists(16);
player.SetKids(14);
}
// Medium
else if(player.Difficulty() == 1)
{
player.SetOre(5000);
player.SetFoodStored(2000);
player.SetWorkers(24);
player.SetScientists(14);
player.SetKids(22);
}
// Hard
else if(player.Difficulty() == 2)
{
player.SetOre(4000);
player.SetFoodStored(1000);
player.SetWorkers(22);
player.SetScientists(12);
player.SetKids(16);
}
}

// ---------------------------------------------- //

void CreateTubeOrWallLine(int x1, int y1, int x2, int y2, map_id type, bool vhpriority);

// Create a line of wall or tube
// Draws between the given coordinates
// If vhpriority is true, it draws horizontal first, then vertical
// else it draws vertical first, then horizontal
void CreateTubeOrWallLine(int x1, int y1, int x2, int y2, map_id type, bool vhpriority)
{

int i;
int vert;
int horz;

// Determine which edges to draw along
if(vhpriority) // Horizontal First
  {
  vert = x2;
  horz = y1;
  }
else // Vertical First
  {
  vert = x1;
  horz = y2;
  }

// Make sure (x1 < x2) and (y1 < y2)
if (x1 > x2){ x1 ^= x2; x2 ^= x1; x1 ^= x2; }
if (y1 > y2){ y1 ^= y2; y2 ^= y1; y1 ^= y2; }

// Create horizontal section
for (i = x1; i <= x2; i++)
  TethysGame::CreateWallOrTube(i, horz, 0, type);
// Create vertical section
for (i = y1; i <= y2; i++)
  TethysGame::CreateWallOrTube(vert, i, 0, type);
}

// ---------------------------------------------- //

Also, I just found out that Outpost2 only reads the first 6 letters of a dll file's name, so if you have dll's named say..."cKramy001.dll" and "cKramy002.dll" it won't distinguish between them at all. :heh: This brings up the possibility of running out of dll names for multiplayer, since we're restricted to very few letter-number combinations for multi... <_<

This was actually also causing a duplicate map problem in the maplist, where one of the options caused op2 to crash.
« Last Edit: June 29, 2004, 06:41:14 PM by Kramy »
-Kramy
001011000100101001110001011000000110110001111000

Offline PlayingOutpost0-24

  • Hero Member
  • *****
  • Posts: 537
    • http://op3np.xfir.net
Outpost 2 DLL Programming
« Reply #24 on: June 30, 2004, 04:19:15 AM »
The ID list:
Strange... Spider is Tech Level 2 but you can only manifacture it on Tech Level 5... :P

Kramy: forgot this:
E - Eden Mission
P - Plymouth Mission
T - Tutorial

Of course, running out will be a time, the first two will be the same, but there is still room for (26 letters + 10 numbers) on the fourth, so it is 36*36*36*36=1,679,616 combinations overall for multiplayer. For single player it is 36*36*36*36*36=60,466,176... So there nothing to be afraid of. Yet. (Of course, subtract those that already are...)

EDIT: there is more, if we count that the file can be shorter than 6 letters...
EDIT2: Forgot that some of the symbols like "_" can be used...
« Last Edit: June 30, 2004, 04:53:00 AM by PlayingOutpost0-24 »
Great news for OP2 fans... OP3 in progress.
Official Site
Outpost 3: A New Power progress
OP3:NP Discussion

Progress in OP3:NP[/size][/font]
PLANNING[|||||||||-]
GRAPHICS [||||------]
SOUNDS [|---------]
MAP DESIGNING [|||||-----]
CODING [----------]
Going slowly... Very slow.