Author Topic: Turrets Won't Fire, And A Thought.  (Read 6726 times)

Fire Plague

  • Guest
Turrets Won't Fire, And A Thought.
« on: June 27, 2008, 03:09:20 PM »
I've placed a fifth player on to the La corrida map, in the center where the AI used to be, but they wouldn't show up. (since only four joined i think) So i used
Player[0].GoAI; which places them on the map and they can be destroyed, but they will not attack (I think it dosen't show on the mini map eather.) it's color was set to Black if that makes any difference.

how dose one get the middle player 5 (human or AI) to shoot at everyone with four human players?

It would be perfect if you could do this and create units/turrets spontaniously at given tick marks after the game has started, much like desasters. how would we do these? THX.  

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Turrets Won't Fire, And A Thought.
« Reply #1 on: June 27, 2008, 03:40:15 PM »
I'm gonna take a guess, and say you probably didn't initialize enough players. Take a look at the DescBlock fields (the first few settings in the source file, where the map name and tech tree are specified), and make sure the number of players is set correctly. Although, usually, the uninitialized player shows up as white on the minimap.


I suppose you can create unit, such as GPs in a time trigger callback. Although, I feel the need to question doing this. It seems odd for buildings to appear out of nowhere.
 

Fire Plague

  • Guest
Turrets Won't Fire, And A Thought.
« Reply #2 on: June 27, 2008, 04:52:27 PM »
I set the DescBlock to "MultiLastOneStanding, 5, 12, 0" before compiling and
places these for the fifth player:

Player[4].GoAI();
    Player[4].GoPlymouth();
    Player[4].SetColorNumber(7);
    Player[4].SetFoodStored(10000);
    Player[4].SetWorkers(50);
    Player[4].SetScientists(20);
    Player[4].SetOre(90000);
    Player[4].SetRareOre(70000);
    Player[4].CenterViewOn(90,60);

Along with the tubes, turrets, and two command centers.

As for the turrets popping out of no where, I wanted to have EMP missles as a desaster type. Perhaps thats different than creating units and such, but i thought it cooler than droping destructive rocks on your head. (dose it require haveing a space port, how would you create this and call a timed trigger you said earlier?)

Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3238
Turrets Won't Fire, And A Thought.
« Reply #3 on: June 27, 2008, 05:08:14 PM »
Well, a few things:
Color 7 = Black, so that explains why the AI is black.
The regular DescBlock doesn't handle multiplayer AI. You need to use DescBlockEx.
First, in the regular DescBlock, set the number of players to however many human players there are (I'm guessing 4). Then, paste this right under the DescBlock:
Code: [Select]
struct SDescBlockEx {
   int unk0;
   int unk1;
   int unk2;
   int unk3;
   int unk4;
   int unk5;
   int unk6;
   int unk7;
};
Oh, and by the way: GoAI gives the player unlimited resources, so you don't need to set its food, population, ore, etc, nor do you have to give it a start location (since it's an AI).
« Last Edit: June 27, 2008, 05:08:49 PM by Sirbomber »
"As usual, colonist opinion is split between those who think the plague is a good idea, and those who are dying from it." - Outpost Evening Star

Outpost 2 Coding 101 Tutorials

Fire Plague

  • Guest
Turrets Won't Fire, And A Thought.
« Reply #4 on: June 28, 2008, 08:42:22 PM »
Well, it initialized the next player in line (we had two people and the computer took player 3) and left the center to sit there. I kind of see how this works but I can't see a way to get it to work without an IF function or know if that IF function will handle such a large list. I know the AI in the La Corrida map would place the computer down dispite the number of players, what did I do wrong?
            4 players, 1 (Fifth) computer.
CODE:

SDescBlock DescBlock   = { MultiLastOneStanding, 4, 12, 0 };
struct SDescBlockEx {
  int unk0;
  int unk1;
  int unk2;
  int unk3;
  int unk4;
  int unk5;
  int unk6;
  int unk7;
};
 SCRIPT_API SDescBlockEx DescBlockEx = { 1, 0, 0, 0, 0, 0, 0, 0 };

Offline Mcshay

  • Administrator
  • Sr. Member
  • *****
  • Posts: 404
Turrets Won't Fire, And A Thought.
« Reply #5 on: June 28, 2008, 09:53:14 PM »
I am assuming that you are, at some point, creating all of the AI's units by hand, correct? If so, create a variable to store the current AI's player number like so:

Code: [Select]
int iAInumber = TethysGame::NoPlayers() - 1;

Then simply replace any instance of your current AI player number with that variable.

Edit: FYI: NoPlayers() returns the number of humans and AI players in the game; this means that its value minus one is the index of your AI player. I'm pretty sure this is how Dynamix did LaCor.

Edit 2: For more help on making the AI do its thing, check out http://forum.outpostuniverse.net/index.php?showtopic=3233
« Last Edit: June 28, 2008, 09:56:27 PM by Mcshay »

Fire Plague

  • Guest
Turrets Won't Fire, And A Thought.
« Reply #6 on: July 12, 2008, 09:10:59 AM »
OK, so the SDK lists several structs to create the randomizing of the baces. I'm trying to get my

four sets of turrets to place themsleves with the bace layouts, but since I can't figrue out how

these structs eventually become a Tethysgame::Createunit... command from it's parts in

structs,(or the array wherever that is), I've ended up with the below codes and A huge list of

errors. The AI also still takes the next starting location after all the players and the assigned

one in the center. the center turrets don;t seem to act like they have an active command center

even though I gave them two. (they'll act like it before I blow up the CP assigned by the

unwanted Hooville player starting bace though)

//this is in BaceBuilder.h (where it starts? I think)

     CODE:
struct TurretInfo
{
   char x;
   enum map_id type;
    int X;
   int Y;
   int p;
   enum map_id weaponCargo;
   int dir;
};


//then these are in the BaceData.h


     CODE:
struct TurretInfo turretset1[] =
{
   {x, mapGuardPost, 48+31, 2-1, 0, mapRailGun, 0};
   {x, mapGuardPost, 48+31, 9-1, 0, mapRailGun, 0};
   {x, mapGuardPost, 3+31, 42-1, 0, mapRailGun, 0};
   {x, mapGuardPost, 10+31, 42-1, 0, mapRailGun, 0};
   {x, mapGuardPost, 46+31, 2-1, 0, mapESG, 0};
   {x, mapGuardPost, 46+31, 9-1, 0, mapESG, 0};
   {x, mapGuardPost, 10+31, 40-1, 0, mapESG, 0};
   {x, mapGuardPost, 3+31, 40-1, 0, mapESG, 0};
   {x, mapGuardPost, 44+31, 2-1, 0, mapStickyfoam, 0};
   {x, mapGuardPost, 10+31, 38-1, 0, mapStickyfoam, 0};
   {x, mapGuardPost, 44+31, 9-1, 0, mapEMP, 0};
   {x, mapGuardPost, 3+31, 38-1, 0, mapEMP, 0};
};

struct TurretInfo turretset2[] =
{
   {x, mapGuardPost, 119+31, 52-1, 1, mapRailGun, 0};
   {x, mapGuardPost, 126+31, 52-1, 1, mapRailGun, 0};
   {x, mapGuardPost, 88+31, 2-1, 1, mapRailGun, 0};
   {x, mapGuardPost, 88+31, 9-1, 1, mapRailGun, 0};
   {x, mapGuardPost, 119+31, 50-1, 1, mapESG, 0};
   {x, mapGuardPost, 126+31, 50-1, 1, mapESG, 0};
   {x, mapGuardPost, 90+31, 9-1, 1, mapESG, 0};
   {x, mapGuardPost, 90+31, 2-1, 1, mapESG, 0};
   {x, mapGuardPost, 92+31, 9-1, 1, mapStickyfoam, 0};
   {x, mapGuardPost, 119+31, 48-1, 1, mapStickyfoam, 0};
   {x, mapGuardPost, 126+31, 48-1, 1, mapEMP, 0};
   {x, mapGuardPost, 92+31, 2-1, 1, mapEMP, 0};
};

struct TurretInfo turretset3[] =
{
   {x, mapGuardPost, 10+31, 82-1, 2, mapRailGun, 0};
   {x, mapGuardPost, 3+31, 82-1, 2, mapRailGun, 0};
   {x, mapGuardPost, 45+31, 119-1, 2, mapRailGun, 0};
   {x, mapGuardPost, 45+31, 126-1, 2, mapRailGun, 0};
   {x, mapGuardPost, 10+31, 84-1, 2, mapESG, 0};
   {x, mapGuardPost, 3+31, 84-1, 2, mapESG, 0};
   {x, mapGuardPost, 43+31, 119-1, 2, mapESG, 0};
   {x, mapGuardPost, 43+31, 126-1), 2, mapESG, 0};
   {x, mapGuardPost, 10+31, 86-1, 2, mapStickyfoam, 0};
   {x, mapGuardPost, 41+31, 119-1, 2, mapStickyfoam, 0};
   {x, mapGuardPost, 3+31, 86-1, 2, mapEMP, 0};
   {x, mapGuardPost, 41+31, 126-1, 2, mapEMP, 0};
};

struct TurretInfo turretset4[] =
{
   {x, mapGuardPost, 74+31, 119-1, 3, mapRailGun, 0};
   {x, mapGuardPost, 119+31, 87-1, 3, mapRailGun, 0};
   {x, mapGuardPost, 126+31, 87-1, 3, mapRailGun, 0};
   {x, mapGuardPost, 74+31, 126-1, 3, mapRailGun, 0};
   {x, mapGuardPost, 76+31, 119-1, 3, mapESG, 0};
   {x, mapGuardPost, 76+31, 126-1, 3, mapESG, 0};
   {x, mapGuardPost, 119+31, 89-1), 3, mapESG, 0};
   {x, mapGuardPost, 126+31, 89-1, 3, mapESG, 0};
   {x, mapGuardPost, 78+31, 126-1, 3, mapStickyfoam, 0};
   {x, mapGuardPost, 126+31, 91-1, 3, mapStickyfoam, 0};
   {x, mapGuardPost, 78+31, 119-1, 3, mapEMP, 0};
   {x, mapGuardPost, 119+31, 91-1, 3, mapEMP, 0};
};

//note the added field here too.

struct BaseInfo base[] =
{
   { autosize(beaconSet1), autosize(buildingSet1), autosize(tubeSet1), autosize(turretset1),

0, autosize(unitSet1) },
   { autosize(beaconSet2), autosize(buildingSet2), autosize(tubeSet2), autosize(turretset2),

0, autosize(unitSet2) },
   { autosize(beaconSet3), autosize(buildingSet3), autosize(tubeSet3), autosize(turretset3),

0, autosize(unitSet3) },
   { autosize(beaconSet4), autosize(buildingSet4), autosize(tubeSet4), autosize(turretset4),

0, autosize(unitSet4) },
};
Here is the Main.cpp if you need any info from there.
« Last Edit: July 12, 2008, 09:12:56 AM by Fire Plague »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Turrets Won't Fire, And A Thought.
« Reply #7 on: July 12, 2008, 06:18:23 PM »
Hmm, I notice that TurretInfo struct seems non standard. I don't have it anywhere in my header files. The idea of the structs though, was they they contain most of the parameters for the function being called. (In this case TethysGame::CreateUnit). The one exception was supposed to be the playerNum, which was excluded from the struct, but seems to be in the one you've just listed.

The reason for excluding the playerNum, was so the structs were not tied to a specific player. This made moving players or base layouts around easier. Instead, the playerNum was meant to be a parameter to the function that iterated over the structs in the array, and created each unit, and supplied the missing playerNum.

I have no idea what that "x" is for.


I took a look at your file. I don't really have time right now to look into the details, but I am impressed with how much effort you've put into it so far. I maybe have a few comments though from just browsing it.

I noticed this line:
Code: [Select]
    Player[ai1].CenterViewOn(90,60);
which will do nothing. Essentialy how Outpost2 implements this function is something like this:
Code: [Select]
void Player.CenterViewOn(int x, int y)
{
 if (Player.playerNum == localPlayerNum)
 {
  // ...
 }
}

So if it's not the local player, then the function does absolutely nothing. This means there is no point in calling it for an AI player. The reason it does this, is so that in multiplayer, you can always initialize all the players in the same way. The game will ignore the call for the remote players, and only do something for the local player. This lets you loop through the players to initialize these things, without having to check which one is the local player before calling that function.

Also, your indentation is a little non stanrdard. Makes it a little harder to read your code.

Oh, and you seem to have a rather complex nesting of "if" statements in the first part of your code. You can probably simplify this section quite a bit. Particularly if you make it more data driven, and less code driven. I'll try to provide more details later on, but I have to go now.
 

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Turrets Won't Fire, And A Thought.
« Reply #8 on: July 13, 2008, 11:49:09 PM »
Ok, I've been taking a look at your code. First of all, there's a much easier way to handle the InitialUnits part. When you have code like that, which is essentially copy+paste work, you can usually redesign it to work better. Make it data driven, instead of code driven.


I've shortened your setup code to the following:

Code: [Select]
	static const map_id weaponType[] = { mapMicrowave, mapLaser };
static const LOCATION playerLoc[] = { LOCATION(49, 14), LOCATION(138, 14), LOCATION(49, 116), LOCATION(138,116)};
Unit unit;
int i, j;
int numHumanPlayers = TethysGame::NoPlayers() - 1;  // Determine number of human players  (Note: Assumes 1 AI player in DescBlockEx)
int ai1 = TethysGame::NoPlayers() - 1;  / Set AI layerNum

// Determine number of Human Players
numHumanPlayers = TethysGame::NoPlayers() - 1;

// Initialize Human Players
for (i = 0; i < numHumanPlayers; i++)
{
  // Give Initial (combat) vehicles
  for (j = 0; j < TethysGame::InitialUnits(); j++)
  {
   TethysGame::CreateUnit(unit, mapLynx, LOCATION(playerLoc[i].x+j, playerLoc[i].y), i, weaponType[Player[i].IsEden()], 0);
   unit.DoSetLights(true);
  }
}

// Enemy "AI" setup stuff
    Player[ai1].GoAI();
    Player[ai1].GoPlymouth();
    Player[ai1].SetColorNumber(7);

// Etc....

Most of your "if" statements seemed to be to find the number of players. By determining the number of players upfront, you can get rid of all of those, and just use a loop. Also, the choice between Eden or Plymouth weapon types was reduced to a table lookup. Player.IsEden just returns 0 or 1, which was used as an index into a type with the two weapon types, instead of the control expression in an "if" statement.



Another thing I noticed was your use of IUnit. This is somewhat non-standard. IUnit was an extension made by the coders here to do a few extra things that OP2 doesn't already have functions for. The IUnit project was maintained by Eddy-B. Since you're not using any of those extension functions, you should probably just use Unit instead. Unit is the exported class from OP2. Just change all the "IUnit" to "Unit", and then remove:
Code: [Select]
#include "IUnit.h"


Btw, the turrets not firing is probably because the AI player has the wrong playerNum. Notice how I changed that ai1 variable to be TethysGame::NoPlayers() - 1. I think that minus one will help.


Edit: I'll post details on determining player indexes in a moment in case it helps. Since it's fairly general knowledge that others will probably find useful, I'll start a new thread.
 
« Last Edit: July 13, 2008, 11:51:09 PM by Hooman »

Fire Plague

  • Guest
Turrets Won't Fire, And A Thought.
« Reply #9 on: July 14, 2008, 05:25:01 PM »
So I've taken a look at the usefull infromation you've spread out for me... which I am thankfull for. However, I noticed on this first look that people thought I couldn't get the turrets to fire correctly. This isn't true. The center AI player dose come up with active and firring turrets (note the verry long trurret creaton inside of InitProc.)  Yet the last "structed" player that came with the SDK (Hooville map) ALSO comes up as AI property as well.

this problem I was trying to eiminate as well as getting the turrets into the structs, or somehow, placed correctly with the correct player. As of right now I'm using a
header file tha places the turrets in the same place regardless of the player's starting position. (ie, player one starts in the lower left corner and player 3's turrets "guard" his land from all the other players because the turrets don't change there placement to where the players are.)

Thanks though  :D

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Turrets Won't Fire, And A Thought.
« Reply #10 on: July 15, 2008, 08:32:59 AM »
I brought up the turrets not firing, because after I gutted parts of the level to get it to compile, and tried running a test, I noticed I could kill the turrets in the middle without them fighting back. Mind you, I'd already heavily edited your code by that point.


Sounds like you could use a bit of help with how to use BaseBuilder.

Btw, you didn't include all the source files in your project, so I commented out the stuff that referenced data that wasn't supplied. This includes all the BaseBuilder stuff. As such, I wasn't able to test that part of your code.


Anyways, keep in mind that you can turn off the player starting location randomization. It's controlled by the line:
Code: [Select]
	// Randomize starting locations
RandomizeStartingLocations(autosize(startLocation));

If you comment that line out of InitProc, then starting locations will be fixed. You can also choose to randomize only some of the starting locations. The actual function is declared as:
Code: [Select]
void RandomizeStartingLocations(int numLocations, struct StartLocation location[]);
If you only want to randomize the first 4, used for Human players, and leave the 5th one fixed, for an AI player, say in the middle of the map, then change the line in InitProc to something like this:
Code: [Select]
	// Randomize starting locations
RandomizeStartingLocations(4, startLocation);

That's assuming you want to randomize the first 4 locations. If you want to randomize n locations starting at location m, then use this:
Code: [Select]
	// Randomize starting locations
RandomizeStartingLocations(n, &startLocation[m]);

You can of course call the function more than once if there are seperate ranges you want to randomize. Maybe you want to randomly swap pairs. Then you can write something like this:
Code: [Select]
	// Randomize starting locations
RandomizeStartingLocations(2, startLocation);  // Randomly swap first 2 (0, 1)
RandomizeStartingLocations(2, &startLocation[2]); // Randomly swap (1, 2)
RandomizeStartingLocations(2, &startLocation[4]); // Randomly swap (3, 4)
// Etc.


I would also like to point out how autosize works:
Code: [Select]
// Used to make autosizing the arrays easier
#define numof(array) (sizeof(array)/sizeof(array[0]))
// Used to make specifying the size of the array and the array easier
#define autosize(array) numof(array), array

Autosize is just a macro that expands to "numArrayElements, array". So if you write:
Code: [Select]
RandomizeStartingLocations(autosize(startLocation));
Then it will expand to something along the lines of:
Code: [Select]
RandomizeStartingLocations(numStartLocations, startLocation);


As for turrets, I think I remember some hack where people put them into the Vehicle list, since the vehicles had an entry for weapons, but the building list didn't.
 

Fire Plague

  • Guest
Turrets Won't Fire, And A Thought.
« Reply #11 on: August 08, 2008, 08:15:24 PM »
Is there a way to enumerate all the buildings of a certian type for a given player, then tally them? Tally them so that it will produce an integer, in the end, which could then be placed in other things. (like an iff function)

I noticed that you can go down a list of buildings in the Enumerator class in the SDK, but none of them seem to be able to spit out the total number of buildings for a certian building type.  :'(

if this is not availible, could a class be written to do this?

this could be placed in the AI Proc() and help controll game values. For example, starting a script_API that gives you somthing, only after you've built your vehilce factory.

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Turrets Won't Fire, And A Thought.
« Reply #12 on: August 10, 2008, 04:22:35 PM »
Two comments. First, you can just count them yourself as you traverse the list of them.

Code: [Select]
// Create the building enum here

while(buildingEnum.GetNext(building))
{
    buildingCount++;
}

Or, after reading what you intend to do with this info, you can just try using one of the triggers that counts this info. Here's the function prototype:

Code: [Select]
OP2 class Trigger __fastcall CreateCountTrigger(int bEnabled, int bOneShot, int playerNum, enum map_id unitType, enum map_id cargoOrWeapon, int refCount, enum compare_mode compareType, char const *triggerFunction);

You might use it something like this:
Code: [Select]
Trigger &vehicleFactCountTrigger = CreateCountTrigger(true, true, playerNum, mapVehicleFactory, mapNone, 1, cmpEqual, "GiveSomething");

SCRIPT_API void GiveSomething()
{
    // Give something here
}

Fire Plague

  • Guest
Turrets Won't Fire, And A Thought.
« Reply #13 on: August 14, 2008, 05:07:50 PM »
The last Idea works geat! thx.  This brings me to phase 2:

Is there a way to prove that a certian type of building is in a certian area. For example if a command center is within a certian area? (rect I believe)
Something that could then send out AI players to destroy the building in the area/rect?

Offline Hidiot

  • Hero Member
  • *****
  • Posts: 1018
Turrets Won't Fire, And A Thought.
« Reply #14 on: August 15, 2008, 04:45:54 AM »
Yes, I believe there is an "InRect" function.

If not, you can always use a RectEnum and look for the specific object you want.


I'd suggest looking in the header filed in the Include folder if you haven't already.
"Nothing from nowhere, I'm no one at all"

Fire Plague

  • Guest
Turrets Won't Fire, And A Thought.
« Reply #15 on: August 20, 2008, 03:35:54 PM »
Seeing it is one thing, scratching out some workable code and understanding it, is another thing all together. I've not looked for it yet, but I don't think I would be able to get some code out of it if I simply saw it's class construtor.

Offline Hidiot

  • Hero Member
  • *****
  • Posts: 1018
Turrets Won't Fire, And A Thought.
« Reply #16 on: August 20, 2008, 05:48:21 PM »
Yeah, but at least you'll know what functions you have on hand and what they do. That way it's easier to make something up yourself than always hitting walls when you need to put the functions together.


One of the first things I did before even starting coding was to read the functions and understand what they do and what each parameter represents. And I still look into them when I need something, but now I know where to look.
"Nothing from nowhere, I'm no one at all"

Fire Plague

  • Guest
Turrets Won't Fire, And A Thought.
« Reply #17 on: August 23, 2008, 02:58:26 AM »
Quote
Code: [Select]
OP2 class Trigger __fastcall CreateCountTrigger(int bEnabled, int bOneShot, int playerNum, enum map_id unitType, enum map_id cargoOrWeapon, int refCount, enum compare_mode compareType, char const *triggerFunction);

You might use it something like this:
Code: [Select]
Trigger &vehicleFactCountTrigger = CreateCountTrigger(true, true, playerNum, mapVehicleFactory, mapNone, 1, cmpEqual, "GiveSomething");

SCRIPT_API void GiveSomething()
{
    // Give something here
}
Well, I couldn't get it to stop creating several "give something" (the time trigger it was on kept reverberating) and the trigger, when placed by itself seemed to run only at the begining of Initprc().
Now my question is, can it be used to constantly test the map and create the "Give something" every time the expression enum compare_mode compare type evaluates to true? it's testing to see if the building is destroyed (Enumerator will then find nothing.) and then re-create it. (or send the AI to build it, once it has one.)
« Last Edit: August 23, 2008, 03:08:47 AM by Fire Plague »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Turrets Won't Fire, And A Thought.
« Reply #18 on: August 23, 2008, 04:59:20 AM »
If you want the AI to build something, you can use a BuildGroup. If something in the build group is destroyed, the AI will try to automatically replace it.

Or, you can try doing it the hard way with triggers.


The second parameter to the Create<X>Trigger functions controls whether or not the trigger should only fire once, or repreatedly. If the second parameter is set to true, it will only fire once, and then get disabled. If the second parameter is set to false, then it will fire every time the triggers are processed (every 4 ticks), provided it's trigger condition is still true.


Btw, try to avoid creating an unbounded number of triggers. If you do, they'll eventually run out and the game will crash. Don't, say, create triggers inside of a time trigger callback that fires repeatedly. At least not unless the destroy the old triggers when they are no longer used.
 

Fire Plague

  • Guest
Turrets Won't Fire, And A Thought.
« Reply #19 on: August 25, 2008, 09:42:09 PM »
It works fine now, thanks for clearifying the count trigger's uses of vars.

Perhaps you would be willing to clearify this as well:

 CODE:

OP2 class Trigger __fastcall CreateVictoryCondition(int boolEnable, int /*Must be zero*/, class Trigger &victoryTrigger, char const *missionObjective);

OP2 class Trigger __fastcall CreateFailureCondition(int boolEnable, int ignoredParam, class Trigger &failureTrigger, char const *notUsed);

so how do you use these triggers?  Dose it activate a "SCRIPT_API void NameHere()" set of instructions? there's nothing that I can find on how to create more than the SDK "CreateLastOneStandingVictoryCondition();" found in OP2helper.h. :'(
(Which dosen't seem to have any refferences to anyother part of the SDK to check how that function got this to work eather BTW)

In the end I wanted to create some block comments that teach a way to create on of each game types. (victory/failure conditions required and some needed checks) for those struggling to map.
                                                    Thanks again.
« Last Edit: August 25, 2008, 10:20:21 PM by Fire Plague »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Turrets Won't Fire, And A Thought.
« Reply #20 on: August 26, 2008, 10:10:29 AM »
If you check OP2Helper.h you'll find the following declarations:
Code: [Select]
// Victory Conditions
void CreateStarshipVictoryCondition();
void CreateLastOneStandingVictoryCondition();
void CreateNoCommandCenterFailureCondition();

You can find the body of these functions in OP2Helper.cpp:
Code: [Select]
void CreateStarshipVictoryCondition()
{
Trigger trig;

// Create victory conditions for - Colony, Starship
trig = CreateCountTrigger(1, 1, -1, mapEvacuationModule, mapAny, 1, cmpGreaterEqual, "NoResponseToTrigger");
CreateVictoryCondition(1, 1, trig, "Evacuate 200 colonists to spacecraft");
trig = CreateCountTrigger(1, 1, -1, mapFoodCargo, mapAny, 1, cmpGreaterEqual, "NoResponseToTrigger");
CreateVictoryCondition(1, 1, trig, "Evacuate 10000 units of food to spacecraft");
trig = CreateCountTrigger(1, 1, -1, mapCommonMetalsCargo, mapAny, 1, cmpGreaterEqual, "NoResponseToTrigger");
CreateVictoryCondition(1, 1, trig, "Evacuate 10000 units of Commom Metals to spacecraft");
trig = CreateCountTrigger(1, 1, -1, mapRareMetalsCargo, mapAny, 1, cmpGreaterEqual, "NoResponseToTrigger");
CreateVictoryCondition(1, 1, trig, "Evacuate 10000 units of Rare Metals to spacecraft");
}


// For use in multiplayer. Note: Computer controlled opponents do not count towards this.
// You win when there is only one human opponent left or all surviving human players are allied.
// This also creates corresponding failure conditions
void CreateLastOneStandingVictoryCondition()
{
Trigger trig;

trig = CreateOnePlayerLeftTrigger(1, 1, "NoResponseToTrigger");
CreateVictoryCondition(1, 1, trig, "Eliminate your opponents.");
}


// (Player 0) fails if the number of active Command Centers becomes equal to 0.
void CreateNoCommandCenterFailureCondition()
{
Trigger trig;

trig = CreateOperationalTrigger(1, 1, 0, mapCommandCenter, 0, cmpEqual, "NoResponseToTrigger");
CreateFailureCondition(1, 1, trig, "");
}

As you can see, they just make calls to create triggers. Note that OP2Helper.h #includes Outpost2DLL.h, which is how it gets access to the trigger functions.

I've noticed the second parameter to Create Victory/Failure Condition doesn't seem to do much. The OP2Helper functions pass true to CreateVictoryCondition, even though the comment says it should be 0 (0=false). Considering the finality of these triggers though, I doubt it matters much. All the Sierra released DLLs seem to pass 0 (false).

The Victory and Failure conditions pretty much create triggers like the other functions do, but they treat a few parameters a little differently. Instead of placing the name of a callback in the final parameter for CreateVictoryCondition, you place the text that appears in game for the list of mission objectives. This same text string is ignored for the Failure condition, so just pass the empty string "".

The Trigger that gets passed in to the Create Victory/Failure Condition functions is what the actual condition is. Multiple Victory Conditions will create multiple mission objectives. Note that if you need multiple conditions to be satisfied for a single Victory condition (such as for the same text string in the mission objectives list), you can use a Set Trigger.

Code: [Select]
OP2 class Trigger __cdecl CreateSetTrigger(int bEnabled, int bOneShot, int totalTriggers, int neededTriggers, char const *triggerFunction,...); // +list of triggers

The Set Trigger is also a bit of an odd one. You'll notice it takes a variable parameter list. What you do is fill in the end of the list with all the triggers that you need to be true (fired) before the Set Trigger is true.


Example:
Code: [Select]
// Create Victory Condition: Have 80-100 workers

Trigger &minWorkersTrigger = CreateResourceTrigger(true, false, resWorkers, 80, 0 /*Player 0*/, cmpGreaterEqual, "NoResponseToTrigger");
Trigger &maxWorkersTrigger = CreateResourceTrigger(true, false, resWorkers, 100, 0 /*Player 0*/, cmpLessEqual, "NoResponseToTrigger");

Trigger &numWorkersTrigger = CreateSetTrigger(true, false, 2, 2, "NoResponseToTrigger", minWorkersTrigger, maxWorkersTrigger);

CreateVictoryCondition(true, false, numWorkersTrigger, "Have between 80 and 100 workers");

These might be a good idea for a compaign where you need to manage your population so you don't starve at the start of the next level due to a lack of agridomes.



Here is a basic population trigger from CES1 (Colony, Eden Starship):
Code: [Select]
Trigger &numColonistsTrigger = CreateResourceTrigger(true, true, resColonists, 450, 0, cmpGraterEqual, "NoResponseToTrigger");

CreateVictoryCondition(true, false, numColonistsTrigger, "Build your population to 450 colonists.");

Of course the actual number of colonists depended on the difficulty setting, so they had three different sets of the above code controlled by a few "if"s, or a switch.



Usually the Victory/Failure conditions are setup in InitProc. This doesn't need to be the case though. I've noticed some Land Rush maps set them up at a later time, such as after a player places their CC. (Some Land Rush maps also set things up in InitProc). There are also some maps that add Victory conditions during the level. In the campaign, I believe there are a few levels where they tell you to research certain techs to win, and more get added as the level goes on.
 

Fire Plague

  • Guest
Turrets Won't Fire, And A Thought.
« Reply #21 on: August 27, 2008, 04:06:55 PM »
So, I wanted to place blight to come on a time trigger as a sudden death type of thing. Obliviously, Ive got the time trigger thing from you, but I can only find a "SetMicrobeSpeed(int speed);" in TethysGame. I checked the Src folder too, now that I know it's got files I can use, but it's only got the op2helper and bacebuilder cpp's.

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Turrets Won't Fire, And A Thought.
« Reply #22 on: August 28, 2008, 07:55:27 AM »
You're looking for Map.SetVirusUL. It's in TethysGame.h, which gets included by Outpost2Dll.h.
 

Fire Plague

  • Guest
Turrets Won't Fire, And A Thought.
« Reply #23 on: August 28, 2008, 06:05:44 PM »
I hear muffled laughter as I'm adding this reply...
CODE:
SCRIPT_API void Blight ()
{
    GameMap::SetVirusUL(LOCATION(64-31,10-1),-1);
    TethysGame::SetMicrobeSpreadSpeed(10);
}

OR

SCRIPT_API void Blight ()
{
    GameMap::SetVirusUL(LOCATION(64-31,10-1),0);
    TethysGame::SetMicrobeSpreadSpeed(10);
}

It's declared like this (note the lack of annotation, the purpose of the int for example.)
static void __fastcall SetVirusUL(struct LOCATION where, int);
*                      So what did I do wrong?
« Last Edit: August 28, 2008, 06:07:34 PM by Fire Plague »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Turrets Won't Fire, And A Thought.
« Reply #24 on: August 29, 2008, 11:13:30 AM »
I believe the int is the spead speed. You can probably do without the second call. I think the second call is if you want to speed up the spread speed at some future point in time.