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

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #50 on: October 10, 2004, 10:49:12 PM »
Well I looked into Unit.DoSimpleCommand today. It's pretty useless. Here's an updated definition all the same. It basically creates a CommandPacket and issues it to the game engine but unfortunatly, the format it creates is only compatible with about 2 or 3 commands. The first 2 are Stop, and SelfDestruct, which already have corresponding exported functions: Unit.DoStop(), and Unit.DoSelfDestruct(). The third possibility is Scatter, but DoSimpleCommand only specifies one unit, so a one unit "scatter" isn't exactly going to get you much. Plus, the function was declared as protected (which affects name decoration, so you can't really change that) so you kinda have to go out of your way to call it.

Code: [Select]
	void DoSimpleCommand(int commandType);

Say, if anyone has a way to get the AI to build an army, I'd like to know about it. I know of one hack that should work but I'm wondering about other ways to go about doing it. I'd like to get the computer to continuously build units, preferable without having to keep ordering it to do so. Maybe one of the group functions?
« Last Edit: October 11, 2004, 12:07:50 AM by Hooman »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #51 on: October 11, 2004, 12:05:38 AM »
That could make for an intersting level. Having units pump out of a garage nonstop.

Anyways, I've looked into Garages a bit and here's what I've got. In the Unit class:
Code: [Select]
	void PutInGarage(int bay, int tileX, int tileY);
You call this on the unit you want to place in the garage (not on the garage you want a unit placed in). The coordinates are the location of the garage (wherever it was built). The bay is of course which slot you want the unit placed in (0-5). The unit must be on the pad of the garage for this to work.

Note: the location of the garage pad is (x-1, y) if you placed the garage at (x,y).

Code: [Select]
	TethysGame::CreateUnit(unit3, map_Garage, LOCATION(46, 10), 0, map_None, 0);
TethysGame::CreateUnit(unit3, map_Cargo_Truck, LOCATION(45, 10), 0, map_None, 0);
unit3.PutInGarage(0, 46, 10);
« Last Edit: October 11, 2004, 12:06:58 AM by Hooman »

Offline PlayingOutpost0-24

  • Hero Member
  • *****
  • Posts: 537
    • http://op3np.xfir.net
Outpost 2 DLL Programming
« Reply #52 on: October 11, 2004, 02:35:10 AM »
is there a way to add a repeat-type command?
maybe every 10 marks it creates 3 lynxes (random wpn) or later panthers and tigers and then every 120 marks it attacks. it continously buids Residences, Agridomes and Med. Centers, DIRTs, expands to beacons... maybe Res., Agri, Med 60 marks + build time, DIRT 90 + build and beacons like... 400 marks.
Is that enough?


Volcanic eruption at 800, but AI has warning systems, so at Mark 700 it moves out with 15 convecs.
At mark 789, a huge meteor hits one of its smelters.
At mark 180 it gets Panther
At mark 320 it gets Tiger
At mark 290 it gets Thor/Nova
At mark 15 it gets Lynx

- Laser already researched
- Adv. lab instantly.
- Fastened research :D




BTW, u now really should compile my dll and c what's w/ it :D


U want more?
« Last Edit: October 11, 2004, 02:35:43 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.

Offline BlackBox

  • Administrator
  • Hero Member
  • *****
  • Posts: 3093
Outpost 2 DLL Programming
« Reply #53 on: October 11, 2004, 06:41:56 PM »
That would be easy to do, just use a time trigger.

CreateTimeTrigger(1, 1, mark*100, "CreateWeapon");

Add CreateWeapon to the .def. then define it as:
void CreateWeapon() {
 TethysGame::CreateUnit( blah blah blah, don't want to list the parameters);

// you could use GetRand to randomize the weapons

}

etc...

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #54 on: October 19, 2004, 09:44:17 PM »
PlayingOutpost: I did compile your DLL. It looks largely fine, but the way the Player[0] and Player[1] was specified seemed to be causing problems. If you just used Player[0] and Player[1] instead of the way you were doing it, it should work fine. Other than that I'm not sure how to help you.


I looked into the positioning of units and structures with TethysGame::CreateUnit. It seems the structures are centered on the coordinates specified. So a Command Center is 3x2 (just the building size, not the size of the bulldozed area) so it is offset by (-1, -1) to find the upper left corner of the building. Note: You must round down when dividing by 2. (It actually shifts right by 1, hence the rounding down). So a call such as:
Code: [Select]
	TethysGame::CreateUnit(unit2, map_Command_Center, LOCATION(46,10), 0, map_None, 0);
Will Create a Command Center centered at (46, 10), so the upper left corner of the Command Center is at (45, 9). Adjusting for the internal coordinates of the game, this would appear to the player as (14, 10) for the upper left corner of the CC.

Also, the internal coordinates of the units are all stored as pixel values and are centered in the tile: (tileX*32+16, tileY*32+16) where each tile is 32x32 pixels. For buildings, the offset of 16 is conditional on the size of the building in that direction. If the size is odd, it gets the 16 pixel offset otherwise it doesn't. (You can think of vehicles as a special case of 1x1 units.) Note: for buildings, the stored value is the center of the building, not the adjusted coordinates for the upper left corner. They might have done this as an easy way to make it when attacking buildings, the weapons hit in the center rather than the upper left corner of the building. Not sure why they'd do this though.

Anyways, so if you were reflecting a base about a certain origin, all the buildings of odd size (in the direction of the flip) will appear an equal distance from the center of the flip. Buildings of even size will be offset by a tile and won't appear symmetric.
 

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #55 on: October 24, 2004, 05:06:34 AM »
Well I've found that TethysGame::AddMessage can only accomodate up to 60 characters. Any more and it'll be truncated. This includes the time stamp the game adds to all messages. (So really you can't use more than 57 characters for the first 10 time marks, 56 for the next 90 time marks, 55 for the next 900 time marks....)



AI ramblings...:

I've continued work on an AI project. I've found out how to enumerate all the beacons on the map. This should allow selection of a beacon to survey and deploy a RoboMiner at. As for which beacon to select, that's another matter. I'm gonna need a few easily programmed heuristics to get this all working nicely. If anyone has any really good ideas out there, I'd love to hear them. Preferably ones that I can program easily.

I'm thinking I should look for the closest mine to the smelter, survey it and deploy a miner at it. If the smelter doesn't exist, then the closest beacon to the miner. I'm thinking I should also add some code to wait on deploying the RoboMiner if more than one beacon is "close" to the smelter until they are all surveyed (unless one is 3 bars, in which case deploy right away). Still no idea on how I'll be defining closeness, or how highly to weight it.

Now, the above certainly isn't perfect but it should largely work. Problems occur with natural obstacles. The closest mine might not be easiest to get to due to ridges. It could have a really long route as compared to a farther mine with a direct route. It might not even be possible to get to it. Rather than distance, I'd prefer to use a route length, but I currently have no real way of calculating that. Besides, even if I found a way of calculating a route distance, it might not match the internal algorithm Outpost2 uses to find routes, and so it wouldn't be accurate since the trucks could take a widely different route. Granted, it should be fairly close in value, but then again, having an active RobotCommandCenter can make a fairly big impact on transit times. (Which reminds me, it's not even the route distance, but the time it takes, which takes terrain type into consideration).

Well, suffice it say, taking distance into account properly isn't really feasible. At least certainly not right now. So good ideas on faking it would be appreciated. Or at least feedback on the simple idea I have.

Another problem is determining where to place new structures. I guess the easy way is to randomly pick a spot adjacent to another building, where there is room. I'd prefer something a little smarter than this though. I don't want buildings placed in the way of ore mines. Also, like like buildings placed in areas depending on the amount of protection they need. For instance, I'd rather have an advanced lab at the back of my base rather than in the front. And a vehicle factory should probably be a little closer to where the units are needed, but not overly exposed. Placing smelters shouldn't be too much of a problem. Just put them close to mines.

Placing buildings in strategic locations isn't so straightforward. What are these locations? How would you find "the back" of your base? Certainly when you play, you'd take natural obstacles into consideration like ridges, and where the breaks are, but it's not so easy to program the computer to find these. It seems like the only real way to defend a base is to scatter units around it. Then you might wonder how hard it'll be to deploy buildings if units are scattered everywhere in the way.

Research doesn't seem to be too much of a problem. I've got the computer to research it's way through a tech tree. A simple minded implementation was to just hardcode a list of research for the computer to work it's way through. There are still a few issues with the list but they'll get worked out soon. (Researches advanced lab stuff at a standard lab, should be easy to check for, and it doesn't really take prerequisites into account, but that is also easy to check for) To my credit, I at least fixed it so it wouldn't assign more scientists than you are allowed to do that research.  :D The more troubling problem is selecting a lab to research at. If there is more than one standard lab, which one will research be done at? So far, I'm just taking the first one found when enumerated, but it might be better to select a lab based on how well defended it is. But then, I'm not sure how to determine "how well defended" it is. I guess I can stick with the assumption that there won't be more than 1 lab, and thus there is no real problem. Anyways, I'd also like to upgrade the research topic selection a little. Maybe make it based on what it needs, or what it's opponents are doing to it. But then I have no clear idea on how to do this sort of objective research. Interestingly enough, I have way of determining pretty much everything about a tech, just no idea how to analyse it. This could also include analysing future changes to the tech files. (I know enough of the internal game structures to determine everything that is read in from the sheets files and even a few more precalculated values).

Resource balancing. When should workers be trained into scientists, and how many. How should workers and scientists be allocated among the buildings. How much ore should go towards base building, resource expansion, military expenditures. I guess some priorties are a little more obvious. Like power is needed before buildings that consume more than you have. But then you might plan on having inactive buildings, so do you take those into account when determining when to build power plants? How long should you put off building agridomes to solve food shortages if you have other pressing needs. Generally you start a level with a shortage but never build agridomes right away. How many smelters should be built and when? Vehicle factories? Extra Command Centers? Special cases like nurseries and universities also have to be considered.

I'm guessing there should be certain priorities to the buildings. Like Always needing a Command Center active. If the computer is being attacked or losing a battle, it might need it's Vehicle Factories all productive. It seems there should be some kind of emergency mode where all resources get put towards defense before any extra is allocated elsewhere. Extra money might be kept in reserve however since you can run out pretty fast. Certain buildings, mainly morale buildings like residences (and maybe agridomes) could have their workers shifted to factories temporarily. Possibly other buildings like nurseries and universities too if there is enough need for defensive production. In normal mode, morale buildings will be important to keep your population up so workers should be assigned to things like residences. Workers must be kept busy so certain buildings may be kept active that aren't strictly needed. But then excess workers might be trained into scientists, or perhaps kept in reserve for buildings that are needed in the near future. Some clear idea as to how to shift these workers around is needed.

Also, for land rush games, where should the base be built? Seems like you should find a decent beacon first. But then you can't wait too long or you starve to death or just get sacked easily.


Anyways, there are my thoughts on what an AI might (should?) consider. I guess I'll have to stick with simplifying assumptions for the meantime. If anyone has any good ideas on how to make a good AI, I'd love to hear them. What it should consider, what simplifying assumptions seem justified, how an algortihm might work, or what problems such a solution might have. Even just what should be focused on first. Right now I think getting an initial resource base going is important, and research is mostly going. Next, probably determining which structure kits to build.
 

Offline Eddy-B

  • Hero Member
  • *****
  • Posts: 1186
    • http://www.eddy-b.com
Outpost 2 DLL Programming
« Reply #56 on: November 18, 2004, 06:15:42 PM »
Hi guys..
i might be new to this forum, but i've read some of it (not all  <_< ).. It seems a lot has been solved/found already. just want to add my little bit, since i could not find a descent explanation about the DescBlock variable.

It should be defined like this:
Code: [Select]
struct SDescBlock{
  int missionType;
  int numPlayers;
  int techLevel;    // Tech-level you start with (in combination with the SetTechLevel function
  bool unitMission;    // false= base mission; true= unit mission (no base commands available)
  char *MapName;
  char *LevelDescription;
  char *TechtreeName;
  int unknown4;
};

It may be someone figured it out already, but i didn't see it yet on this forum...
Rule #1:  Eddy is always right
Rule #2: If you think he's wrong, see rule #1
--------------------

Outpost : Renegades - Eddy-B.com - Electronics Pit[/siz

Offline Eddy-B

  • Hero Member
  • *****
  • Posts: 1186
    • http://www.eddy-b.com
Outpost 2 DLL Programming
« Reply #57 on: November 20, 2004, 04:37:32 PM »
Quote
Or even how many fields should be in this structure?
This is definately THE number of arguments, although the last "unknown" argument seems to be always zero, and has no effect when changed...
it might just be a filler to get to an 8-Byte offset, who knows. For now, just leave it in as "unknown" and don't worry about it too much i guess.

Code: [Select]
struct SDescBlock{
int missionType;     // For campaign games, this is the level number (positive values)
int numPlayers;      // For multiplayer, this is the number of players. For singleplayer, set to 2 when using computer opponent !
int techLevel;         // Tech level for available research
bool unitMission;       // true=unitmission; false=basemission
char *MapName;
char *LevelDescription;
char *TechtreeName;
int unknown;
};
[/font]
The whole DescBlock structure is now 32 bytes long.
« Last Edit: November 20, 2004, 04:41:08 PM by Eddy-B »
Rule #1:  Eddy is always right
Rule #2: If you think he's wrong, see rule #1
--------------------

Outpost : Renegades - Eddy-B.com - Electronics Pit[/siz

Offline Eddy-B

  • Hero Member
  • *****
  • Posts: 1186
    • http://www.eddy-b.com
Outpost 2 DLL Programming
« Reply #58 on: November 21, 2004, 06:45:30 AM »
Okay Hooman, how about this:

I'm trying to set up an AI, but i didn't get far...
I'm trying to figure out how to have it create structure kits at its newly build factory. I've seen you use CreateBuildingGroup, but this works only if you have the units' addresses. Now how do i get the address of a newly constructed structure.

Code: [Select]
Unit convec1,convec2;
int x=60,y=10;

EXPORT void CreateTrucks()
{
   TethysGame::CreateUnit(convec1,map_ConVec,LOCATION(46,0),0,map_Command_Center,1);
   convec1.DoBuild(map_Command_Center,LOCATION(x,y));
   TethysGame::CreateUnit(convec2,map_ConVec,LOCATION(48,0),0,map_Structure_Factory,1);
   convec2.DoBuild(map_Structure_Factory,LOCATION(x+5,y+1));

   CreateOperationalTrigger(1,1,1,map_Structure_Factory,1,cmp_Equal,"Base1");
}

EXPORT void Base1()
{
   BuildingGroup &bldGrp1 = CreateBuildingGroup(Player[0]);
   bldGrp1.TakeUnit(convec1);
   bldGrp1.TakeUnit(convec2);
   bldGrp1.RecordBuilding(LOCATION(x+1,y+3),map_Agridome,map_None);
}
I've checked my trigger - it works fine, but the "AI" simply won't do any construction. My guess is i need to add the structure factory to the BuildingList, but how ??

Any help ?



PS: you need to define this to be able to export any functions:
Code: [Select]
#define EXPORT extern "C" __declspec(dllexport)
« Last Edit: November 21, 2004, 07:58:06 AM by Eddy-B »
Rule #1:  Eddy is always right
Rule #2: If you think he's wrong, see rule #1
--------------------

Outpost : Renegades - Eddy-B.com - Electronics Pit[/siz

Offline BlackBox

  • Administrator
  • Hero Member
  • *****
  • Posts: 3093
Outpost 2 DLL Programming
« Reply #59 on: November 21, 2004, 10:58:04 AM »
I think you can call .DoBuild() of the structure factory unit class to make it produce a structure kit.
You can use an enumerator to get the structure factory Unit object.

but anyway, to add the factory to the building group, get it's Unit object and use .TakeUnit() to add it. (Structures are considered to be Units)

FYI: You don't need the #define EXPORT stuff to export a function.
Just remove all the qualifiers from the function prototype and add the function name to the .def file (which should be part of the project).

That's how every other function is exported, (look at the .def to see)

Offline Eddy-B

  • Hero Member
  • *****
  • Posts: 1186
    • http://www.eddy-b.com
Outpost 2 DLL Programming
« Reply #60 on: November 21, 2004, 11:08:34 AM »
Quote
Just remove all the qualifiers from the function prototype and add the function name to the .def file (which should be part of the project).
Well, i find it easier this way: i've been programming for 19 years now, and i'm the kind of guy that can be compared mostly to what nature doez: resist changes { you know, the things Newton and Einstein propagate }
In other words: when using this EXPORT structure, you don't need to have an extra .def file in your project. In fact i compiled my dll's withoutANY def file. My philosophy: one less file to worry about !

As for the other part: i did look into the EnumerateBuildings function, but couldn't quite figure it out. Tried looking at the 2 "unknown" members. First one seems to be some pointer, while the 2nd looks more like an int or char kind of variable.
Unknown1 does NOT point to a Unit class, since casting to a Unit and accessing a member causes Outpost to crash !

Hey, help me out here !  I might be 'hardened' programmer, but i'm not an experienced hacker nor do i know a lot about Outpost2 programming (YET!) I do find it fascinating though that Sierra online used DLLs instead of just .map files like most gaming engines do. I have build mappers for the X-Wing and Tie-Fighter games with ease... but this ..  <_<

BTW; The source i've submitted before (see below) sets up 2 ConVecs with the 2 key structures you need to start a game, and having the player (or computer) start really "From scratch"

Thanx for your help, and i hope I can help you guys further also !

Quote
Code: [Select]
Unit convec1,convec2;
int x=60,y=10;

EXPORT void CreateTrucks()
{
  TethysGame::CreateUnit(convec1,map_ConVec,LOCATION(46,0),0,map_Command_Center,1);
  convec1.DoBuild(map_Command_Center,LOCATION(x,y));
  TethysGame::CreateUnit(convec2,map_ConVec,LOCATION(48,0),0,map_Structure_Factory,1);
  convec2.DoBuild(map_Structure_Factory,LOCATION(x+5,y+1));

  CreateOperationalTrigger(1,1,1,map_Structure_Factory,1,cmp_Equal,"Base1");
}

EXPORT void Base1()
{
  BuildingGroup &bldGrp1 = CreateBuildingGroup(Player[0]);
  bldGrp1.TakeUnit(convec1);
  bldGrp1.TakeUnit(convec2);
  bldGrp1.RecordBuilding(LOCATION(x+1,y+3),map_Agridome,map_None);
}
« Last Edit: November 21, 2004, 11:10:45 AM by Eddy-B »
Rule #1:  Eddy is always right
Rule #2: If you think he's wrong, see rule #1
--------------------

Outpost : Renegades - Eddy-B.com - Electronics Pit[/siz

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #61 on: November 21, 2004, 12:48:23 PM »
Ok, this seems like an easy problem to fix. Move the Building group to InitProc. The Operation Triggers will only fire once the building is built and operational. If the ConVecs never build the buildings, it'll never fire. Besides, all the original DLLs use InitProc to setup stuff like that. It's starting to feel like an establised standard  :P . If you really want to add stuff to the group as it's created, I'd suggest making the group a global variable and then add units or recorded buildings to the group in you triggers/other functions. If you want to add a unit to the group as it's created, take a look at the enumerator classes. I've used that in a project in AIProc to add units to groups after they are created. Keep in mind that it'll enumerate all units of that type (or all units) and it won't return any useful results until the unit is created. AIProc is called every game cycle (or every 4 games cycles) so you can put any continuous checks you need in there. (Probably better ways to do most of that though).

And yeah, I've noticed that about the .def files too. I've stopped using it for new functions but I've been to lazy to remove it for functions already using it. I stay away from the #define though. I've never really liked #define.  (thumbsdown) Heh, you should see some of the bugs they can cause.

Quote
Unknown1 does NOT point to a Unit class, since casting to a Unit and accessing a member causes Outpost to crash !
Yes, most definately. These aren't really unknown anymore. Just that the values aren't really useful and I'd rather people not try and use them. (And I'm too lazy to update the header file  :P ) Besides, what have you been told about accessing class member veriables!  :lol:

The problem with the above is that OP2 doesn't use any of the exported classes internally. They are just wrappers for the internal classes. What you're seeing I believe IS a pointer to a Unit class, just not the exported one. If for some reason people really need access to that stuff, I'll release a library but I'm still a little hesitant to post much info on it.

To use the enumerators, construct a new one everytime to want to enumerate.
Code: [Select]
PlayerBuildingEnum enm(playerNum, buildingType);
Where playerNum is from 0-6 and buildingType is one of the map_id enum constants in Outpost2DLL.h.
Then you need a Unit variable to hold the returned unit from the enumeration.
Code: [Select]
Unit unit;
enm.GetNext(unit);
If the return value of GetNext is non-zero, then a unit was returned and copied into "unit". (Actually, all the Unit class is, is a wrapper for the internal class and all it really contains is the unitID, which is just the index of the inernal unit class in an array. So don't worry about it copying large objects, it's only 4 bytes).
If you only want one unit, you can do that (but be sure to actually check the return value is non-zero before trying to use the unit) or, if you need all units of that type, throw the GetNext into a loop.
Code: [Select]
While(GetNext(unit))
{
// whatever
}


Edit: Come join us on IRC in channel #Outpost2.tutor. That's were all the programming stuff is talked about. (They get tired of us flooding the gaming channel with technical info).  :lol:  
« Last Edit: November 21, 2004, 12:49:51 PM by Hooman »

Offline Eddy-B

  • Hero Member
  • *****
  • Posts: 1186
    • http://www.eddy-b.com
Outpost 2 DLL Programming
« Reply #62 on: November 21, 2004, 12:59:19 PM »
Got it to work, but i overlooked one slight thing. Anyway, here's how it works:
{ appearently, while YOU were typing YOUR reply..  :P }

Quote
Code: [Select]
Unit convec1,convec2;
int x=60,y=10;

EXPORT void CreateTrucks()
{
  TethysGame::CreateUnit(convec1,map_ConVec,LOCATION(46,0),0,map_Command_Center,1);
  convec1.DoBuild(map_Command_Center,LOCATION(x,y));
  TethysGame::CreateUnit(convec2,map_ConVec,LOCATION(48,0),0,map_Structure_Factory,1);
  convec2.DoBuild(map_Structure_Factory,LOCATION(x+5,y+1));

  CreateOperationalTrigger(1,1,0,map_Structure_Factory,2,cmp_Equal,"Base1");
}

EXPORT void Base1()
{
  PlayerBuildingEnum bldgs=PlayerBuildingEnum(0,map_Structure_Factory);
  bldgs.GetNext(unit);

  BuildingGroup bldGrp1 = CreateBuildingGroup(Player[0]);
  bldGrp1.TakeUnit(unit);  // the structure factory
  bldGrp1.TakeUnit(convec2);
  bldGrp1.RecordBuilding(LOCATION(x+1,y+5),map_Agridome,map_None);
}

Anywayz; what i forgot { and figured out, when i gave the 2 trucks 'human' control } is that when the mission starts, and all you have is the 2 ConVecs with the kits inside, and NO ore storage facilities, your ore immediatly turns to zero, making it impossible to build anything more than just that what you have kits for.
So in order to have someone "start from scratch" you'll need at least:
  • command center
  • structure factory
  • tokamak
  • smelter
  • at least 1 convec
  • at least 1 cargo truck
  • at least 1 surveyer
  • at least 1 miner (or 1 ore mine, which also cancells out the surveyer)
Rule #1:  Eddy is always right
Rule #2: If you think he's wrong, see rule #1
--------------------

Outpost : Renegades - Eddy-B.com - Electronics Pit[/siz

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #63 on: November 21, 2004, 01:04:35 PM »
Ahh yes. I see now that I misread your code. I guess what threw me off was the EXPORT for the CreateTrucks function. I'm kinda wondering why it's exported now? I assume you already know this, but just in case, only Trigger callbacks and the required functions already given in the template file need to be exported.

Heh, last time I had a building group and no money, I heard a lot of that sound that plays when your order is cancelled due to lack of ore.

 

Offline Eddy-B

  • Hero Member
  • *****
  • Posts: 1186
    • http://www.eddy-b.com
Outpost 2 DLL Programming
« Reply #64 on: November 21, 2004, 01:30:00 PM »
Quote
AIProc is called every game cycle (or every 4 games cycles) so you can put any continuous checks you need in there. (Probably better ways to do most of that though).
Thats how i did it at first, before reading about the triggers. It's just that the whole thing is missing one important trigger: BuildingDone or something likewise. But anyway: the BuildingGroup makes it a lot easier to make an AI.
Q: Is there a simular procedure for building vehicles at the factory ? if not: is there a trigger when a vehicle is build ??
Rule #1:  Eddy is always right
Rule #2: If you think he's wrong, see rule #1
--------------------

Outpost : Renegades - Eddy-B.com - Electronics Pit[/siz

Offline BlackBox

  • Administrator
  • Hero Member
  • *****
  • Posts: 3093
Outpost 2 DLL Programming
« Reply #65 on: November 21, 2004, 02:07:57 PM »
to build stuff at a vehicle factory, you can use the .DoBuild() member, again.

However if you need to create it with a cargo / weapon it has to be done through a BuildingGroup (don't remember now, how to do that)

As for a trigger when a vehicle is built, you could do this:

Trigger &trig = CreateCountTrigger(1, 1, playerID, unitType, cargoType, 1, cmp_Greater_Equal, "VehicleCreated");

that would fire if 1 or more of the unitType units existed with cargo cargoType. If you wanted to know if it was created you'd have to figure out how many units there were beforehand (probably need an enumerator), then compare the count to numUnits + 1 to see if it exists yet.

Or you could enumerate thru them in AIProc() and check for changes in the values...

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #66 on: November 21, 2004, 05:08:41 PM »
For combat vehicles, there is some group commands you can use that Haxtor found. Check the post http://forum.outpostuniverse.net/index.php?showtopic=116...indpost&p=26169 for details. It uses UnitBlocks and BuildingGroups to do it.

There is a way to specifically order a vehicle factory to build a unit using DoDevelop(), but not combat units. You have to use the above mentioned method for that. The problem with combat units is the weapon isn't set properly, so the game crashes once the unit is built. Also, I believe DoBuild() only works for deploying strucutres and mines (but is kinda sick with mines). I don't believe it'll work for building stuff at a factory. I could be wrong though.
 

Offline Eddy-B

  • Hero Member
  • *****
  • Posts: 1186
    • http://www.eddy-b.com
Outpost 2 DLL Programming
« Reply #67 on: November 26, 2004, 01:40:12 PM »
Hey guys, another thing you can ADD to the Outpost2DLL.h headerfile:
Code: [Select]
enum trig_res {
   res_food  = 0,
   res_common_ore,
   res_rare_ore,
   res_kids,
   res_workers,
   res_scientists,
   res_colonists
};
The res_common_ore and res_rare_ore lines are there already, so just overwrite them with the above (copy&paste).

Always happy to help out !

Cheerz  :D
Eddy-B



{edit} PS: res_colonists is kids+workers+scientists
« Last Edit: November 26, 2004, 01:41:11 PM by Eddy-B »
Rule #1:  Eddy is always right
Rule #2: If you think he's wrong, see rule #1
--------------------

Outpost : Renegades - Eddy-B.com - Electronics Pit[/siz

Offline Eddy-B

  • Hero Member
  • *****
  • Posts: 1186
    • http://www.eddy-b.com
Outpost 2 DLL Programming
« Reply #68 on: November 26, 2004, 07:38:18 PM »
Well,, several hours later, and i found some more AI entries into the great mysteries of outpost2.exe:
Update your outpost2DLL.h to include this part:
Code: [Select]
struct OP2 PatrolRoute {
   int unknown1;
   LOCATION *waypoints;
   int unknown[10];
};
Look for the definition of PatrolRoute, and copy&paste the middle 3 lines of the above code in between the braces as shown.
Now, the way you use this is as follows:
Code: [Select]
void SetPatrol()
{
   LOCATION scoutRoute[]=
   {
      LOCATION(120, 14),
      LOCATION( 80, 14),
      LOCATION( 96, 24),
      LOCATION( -1, -1)
   };
   PatrolRoute route1;
   route1.waypoints=scoutRoute;

   patrolGrp=CreateFightGroup(Player[1]);
   patrolGrp.SetPatrolMode(route1);
   patrolGrp.TakeUnit(scout1);     // assuming scout1 was already created
}
The scoutRoute array contains the waypoints my scout will follow. You can set upto 8 waypoints, after wich the scout will continue from its first waypoint again. If you want less than 8 waypoints, mark the end of the list with a LOCATION(-1,-1)

It's as simple as that !

[size=8](don't i get credits for this or what ARE those credits for ???)[/size]
Rule #1:  Eddy is always right
Rule #2: If you think he's wrong, see rule #1
--------------------

Outpost : Renegades - Eddy-B.com - Electronics Pit[/siz

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #69 on: December 09, 2004, 07:23:14 PM »

Ok, I just did some thread pruning. I know some people have wanted this thread to be a little better organised and easier to read so I've deleted most of the posts that don't add now useful technical content. There are still a few that contain obsolete technical content that will probably be either edited or deleted at a later point. (I hope I haven't interrupted the flow of thought too much by doing all this.)

I'd like to thanks everyone who contributed. Some very good questions were raised. Unfortuneately I didn't deem many good questions to be good techincal content so your posts have been deleted.  ;)

Anyways, I thought I'd list/thank a few people who have contributed but who's posts (some/most/all of them) have been deleted.
Arklon, Cynex, Ezekel, Hacker, Haxtor, Kramy, Leviathan, PlayingOutpost, Saibot.

Keep it coming people (, I can just keep pruning!  :lol: )

 

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #70 on: January 05, 2005, 12:37:43 AM »
Figured I'd post a few updates before people started thinking this thread was dead.

Code: [Select]
	static void __fastcall SetMusicPlayList(int numSongs, int repeatStartIndex, enum SongIds *songIdList);

The songIdList is an array of SongIds. These are the songs that OP2 will play in the background. Playing begins at the first song (index 0) and when the lists is finished, playing continues by looping back to the song at index repeatStartIndex. (Thanks Eddy, seems like that repeat idea was right).

And here is a filled in SongIds enum and associated filenames (sorta).
Code: [Select]
enum SongIds {
songEden11 = 0,
songEden21,
songEden22,
songEden31,
songEden32,
songEden33,
songEP41,
songEP42,
songEP43,
songEP51,
songEP52,
songEP61,
songEP62,
songEP63,
songPlymth11,
songPlymth12,
songPlymth21,
songPlymth22,
songPlymth31,
songPlymth32,
songPlymth33,
songStatic01,
songStatic02,
songStatic03,
songStatic04,
songStatic05
};



Another few sound/messaging functions:
Code: [Select]
	// Note: Recorded voice messages can be played by specifying the right soundID
static void __fastcall AddGameSound(int soundID, int recipientPlayerNum);
static void __fastcall AddMapSound(int soundID, struct LOCATION location);
static void __fastcall AddMessage(int pixelX, int pixelY, char *message, int recipientPlayerNum, int soundID);
static void __fastcall AddMessage(class Unit, char *message, int recipientPlayerNum, int soundID);

AddGameSound just play a sound which the given player hears. You can use -1 to make it heard by all players.

AddMapSound is used to place a directional sound like fumaroles. When their current view is over that section of the map, they will hear this sound continuously. (Kinda annoying actually  <_< ) If they are close to that section of the map then the sound will play quietly and you won't hear it at all if you're far enough away.

AddMessage places a message in the communcations pane. Use coordinates (-1, -1) if you want to disable the spacebar jumpto feature for this message. Otherwise, enter the *pixel* coordinates of where on the map this message will take the view on a jumpto. Note that you must multiply the tile coordinates by 32 to obtain the pixel coordinates. (The usualy tile offsets apply). Using a soundID of 0 will play the default beep you normally hear when messages are added to the communications pane. The "class Unit" version of this function works the same as the other form except the location for the jumpto is taken to be the coordinates of the unit. (The view is centered on where that unit was at the time the message was added for the jumpto).


Btw, anyone have a better name than "recipientPlayerNum"? Personally I can't stand that variable name and changing it won't affect anything, not even existing code. It'd be nice to change it to something a little more intuitive sounding before another release of the header file though.


In another note, I'm getting pretty sick of the "_"s in enum names and I've heard a few people prefer them not being there so in the next update I'd like to have them removed. As for people who already have code with the underscores, I think we should leave in some compatibility option so your code should still compile. Maybe phase them out slowly (but completely!   :angry: ). Ok, yeah, so I'm a little biased against the underscores.
« Last Edit: January 05, 2005, 12:41:03 AM by Hooman »

Offline BlackBox

  • Administrator
  • Hero Member
  • *****
  • Posts: 3093
Outpost 2 DLL Programming
« Reply #71 on: January 05, 2005, 03:13:48 PM »
I agree.. I suggest we use the identifiers that the sheets.vol and the rest of the game use. (but probably lower case of course. Also, the current names are full of spelling mistakes)

Yes, some sort of compatibility option. Maybe a #define in the header file to allow the old names?

eg.
Code: [Select]
#define USE_OLDNAMES
#include "../Outpost2DLL.h"

Offline Eddy-B

  • Hero Member
  • *****
  • Posts: 1186
    • http://www.eddy-b.com
Outpost 2 DLL Programming
« Reply #72 on: January 05, 2005, 06:35:59 PM »
better yet: why not keep both names ?
i know it's a lot of typing, but at least it's backward-compatible!

#define map_None  mapNone
#define map_Cargo_Truck mapCargoTruck

etc..
Rule #1:  Eddy is always right
Rule #2: If you think he's wrong, see rule #1
--------------------

Outpost : Renegades - Eddy-B.com - Electronics Pit[/siz

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Outpost 2 DLL Programming
« Reply #73 on: January 06, 2005, 07:12:59 PM »
Lol, guys there is a really simple way

copy and paste, and then delete all the underscores. Also, maybe throw a #define around one set so they can be removed to test if your code compiles under the new names.

enum map_id
{
mapNone = 0,
.
.
.

#ifdef OLD_NAMES // Meh, why not use an underscore in this name ;)
map_None = 0,
.
.
.
#endif
}


And spelling mistakes? I've only really noticed one that Eddy pointed out to me.
 

Offline BlackBox

  • Administrator
  • Hero Member
  • *****
  • Posts: 3093
Outpost 2 DLL Programming
« Reply #74 on: January 07, 2005, 02:36:08 PM »
Hmm. I see these:
   map_Nursury,            // 23
   map_Athiest_Building_Explosion,         // 57
   map_Pheonix_Module,         // 63
There's probably more.

But anyway, we should rename them to something simple. (So it's not a guessing game trying to remember the EXACT name of the constant. Like, map_Robot_Command or map_Robot_Command_Center ? (And it's ridiculously long to type)
It should also be immediately apparent what things are. (What is map_Energy_Cannon? I'd THINK it's the scorpion laser, but I'm not certain)

We also need to fill in all the parameters with information that makes the usefulness of the function more apparent.