Page 1 of 1

Trouble with Unitdef.h file

Posted: 21 Sep 2005, 19:56
by Veylon
I don't know if I have an old file or what, but when I tried using getting the unitdef structure by
callback->GetUnitDef("UNIT"), it was messed up, so I had to put an array of 28 bytes into the unitdef struct to get it to work (after the names, but before loaded).

Code: Select all

struct UnitDef
{
string name
// etc.
int Unknown

bool loaded
// ...
Does anyone know the why of this?

Posted: 21 Sep 2005, 20:15
by AF
hmmm

Code: Select all


const UnitDef* ud;
ud = callback->GetUnitDef("cormex");

That works for me....

Though did you really try asking for the unti that goes by the unit name of "UNIT"?! Try adding code to check for a zero return value, I think you'll find that much more helpful than an engine crash,

Code: Select all


const UnitDef* ud;
ud = callback->GetUnitDef("cormex");
if(ud == 0){
return false;
} else {
etc.....
}


Posted: 21 Sep 2005, 20:18
by Veylon
My issue is that I used the same code as you, but for every unit I got the unit code of 15.

Adding some padding to the beginning worked, because I did a binary dump of the structure and found the offset that was creating the error.

Again, what you have should've worked for me, but it didn't.

Posted: 21 Sep 2005, 20:25
by AF
huh?

Post your code in its entirety, I've never recieved such errors. And remember that you should never change the unitdef structures you get given as they point to those used by the engine itself, and could destabilise things and lead to messy happenings, or a potential for cheating and unsyncing when using groupAI

Posted: 21 Sep 2005, 21:18
by jcnossen
What compiler are you using, VStudio .NET?
In any case, make sure you use the same struct-alignment as the spring engine does, this is configurable somewhere in the project settings.

Hmm, spring uses "default" alignment, whatever that may be....

Posted: 22 Sep 2005, 00:05
by Veylon
Actually, I have Visual Studio 6.0. I don't know how to do anything with alignment, and probably won't since all my crashes were before I changed the file.

I have my AI printing off of a list of it's doings and some unit data, and it matches with the FBI's, so I'm not too eager to put things back the way they were before.

Anyway, I don't have my code right now (I'm not at home), but I'll try to get it up here next time I can get online.

Posted: 27 Sep 2005, 19:42
by Veylon
OK. I think I solved the problem. Here's my UnitDef3.h File:

Code: Select all

#ifndef UNIT_DEF_STRUCT
#define UNIT_DEF_STRUCT

#pragma once

#include <string>
#include <vector>
#include <map>

struct MoveData;
struct WeaponDef;

// Special Format

struct StrDat
{
	unsigned char           Empty [4];
	union _IntData
	{
		struct _HasPointer
		{
			char*			    Pointer;
			unsigned char     Empty[12];
		} HasPointer;
		char                 IntName[16];
	} IntData;
	int							StrLength;
	int							StrMaxLength;
};

struct GuiSound
{
	StrDat name;
	int id;
	float volume;
};

struct UnitModelDef
{
	StrDat modelpath;
	StrDat modelname;
	std::map<StrDat, StrDat> textures;
};



char *StrDatOut(const StrDat* String)
{
	if(String->StrLength < 16)
		return (char *)String->IntData.IntName;
	else
		return String->IntData.HasPointer.Pointer;
}
/*
char *StrDatOut(const StrDat String)
{
	return StrDatOut(&String);
}
*/

struct UnitDef
{
	StrDat	Name;
	StrDat	HumanName;
	StrDat	FileName;
	
	bool loaded;
	int id;											//unique id for this type of unit
	unsigned int unitimage;

	int aihint;


	float metalUpkeep;
	float energyUpkeep;
	float metalMake;	//metal will allways be created
	float makesMetal;	//metal will be created when unit is on and enough energy can be drained
	float energyMake;
	float metalCost;
	float energyCost;
	float buildTime;
	float extractsMetal;
	float extractRange;
	float windGenerator;
	float tidalGenerator;
	float metalStorage;
	float energyStorage;

	float power;
	float health;
	unsigned int category;

	float speed;
	float turnRate;
	int moveType;
	bool upright;

	float controlRadius;
	float losRadius;
	float airLosRadius;
	float losHeight;

	int radarRadius;
	int sonarRadius;
	int jammerRadius;
	bool stealth;

	float buildSpeed;
	float buildDistance;
	float mass;

	float maxSlope;
	float maxHeightDif;									//maximum terraform height this building allows
	float minWaterDepth;
	float waterline;

	float maxWaterDepth;

	float armoredMultiple;
	int armorType;

/*	UnitModelDef model;

	struct UnitDefWeapon {
		UnitDefWeapon(StrDat name,WeaponDef* def,int slavedTo,float3 mainDir,float maxAngleDif,unsigned int badTargetCat)
			: name(name),
				def(def),
				slavedTo(slavedTo),
				mainDir(mainDir),
				maxAngleDif(maxAngleDif),
				badTargetCat(badTargetCat) {}

		StrDat name;
		WeaponDef* def;
		int slavedTo;
		float3 mainDir;
		float maxAngleDif;
		unsigned int badTargetCat;
	};
	std::vector<UnitDefWeapon> weapons;

	std::map<int,StrDat> buildOptions;
*/
	char Unknown1[0x60];

	StrDat unittype;
	StrDat tooltip;
	StrDat wreckName;

	StrDat deathExplosion;
	StrDat selfDExplosion;

	StrDat TEDClassString;	//these might be changed later for something better
	StrDat categoryString;

	int selfDCountdown;

	bool canfly;
	bool canmove;
	bool canhover;
	bool floater;
	bool builder;
	bool activateWhenBuilt;
	bool onoffable;

	//aircraft stuff
	float wingDrag;
	float wingAngle;
	float drag;
	float frontToSpeed;
	float speedToFront;
	float myGravity;

	float maxBank;
	float maxPitch;
	float turnRadius;
	float wantedHeight;
	bool hoverAttack;

	float maxAcc;
	float maxDec;
	float maxAileron;
	float maxElevator;
	float maxRudder;

	MoveData* movedata;
//	unsigned char* yardmapLevels[6];
	unsigned char* yardmap;				//Used for open ground blocking maps.

	int xsize;									//each size is 8 units
	int ysize;									//each size is 8 units

	float loadingRadius;	//for transports
	int transportCapacity;
	int transportSize;
	bool stunnedCargo; // are the units stunned while being transported?

	bool canCloak;							//if the unit can cloak
	bool startCloaked;					//if the units want to start out cloaked	
	float cloakCost;						//energy cost per second to stay cloaked when stationary
	float cloakCostMoving;			//energy cost per second when moving
	float decloakDistance;			//if enemy unit come within this range decloaking is forced

	bool canKamikaze;						//self destruct if enemy come to close
	float kamikazeDist;

	bool targfac;
	bool canDGun;
	bool needGeo;
	bool isFeature;
	bool hideDamage;
	bool isCommander;

	bool canResurrect;
	bool canCapture;
	int highTrajectoryType;			//0(default)=only low,1=only high,2=choose

	unsigned int noChaseCategory;

	struct SoundStruct {
		GuiSound select;
		GuiSound ok;
		GuiSound arrived;
		GuiSound build;
		GuiSound repair;
		GuiSound working;
		GuiSound underattack;
		GuiSound cant;
		GuiSound activate;
		GuiSound deactivate;
	};
	SoundStruct sounds;

	bool leaveTracks;
	float trackWidth;
	float trackOffset;
	float trackStrength;
	float trackStretch;
	int trackType;

	bool canDropFlare;
	float flareReloadTime;
	float flareEfficieny;
	float flareDelay;
	float3 flareDropVector;
	int flareTime;
	int flareSalvoSize;
	int flareSalvoDelay;

	bool smoothAnim;			// True if the unit should use interpolated animation
};


#endif
I made a new string structure and replaced all the std::strings with StrDat.
This didn't work for model info or weapons, so I paved them over with a 96-byte unknown block.
This probably breaks a dozen or so rules of civilized C++ coding, but at least now I can read the string.

Posted: 27 Sep 2005, 20:34
by AF
Yes but can you now use this ingame? I believe you would be being returned unitdef structure type A, and trying to put it into unit structure type b(your edited version), which is simply not right.

Posted: 27 Sep 2005, 20:40
by jcnossen
Even if it works, this way of doing it is a major hack and should always be avoided. Realize that you have to keep it in sync with the CVS unitdef.h, and all your users will need to download updates for this every time. imo, You really should find out what the real problem is here instead of working around it.

Posted: 28 Sep 2005, 21:15
by Veylon
Atlantai: It does work in game. The StrDat class is a wrapper of the std::string data. Yesterday I added a c_str() member function to replicate the functionality of string.

Zaphod: I would love to avoid using an ugly hack. The only reason I am doing so is because the string class does not work for me in communicating with Spring. If you or anyone else knows how to fix it, I would welcome your input.
I know that I should use the same STL strings that the rest of Spring uses, but it does not work. For instance, this crashes the program on my computer:

Code: Select all

char c[200];
const string myString = callback->GetUnitDef("CORSOLAR").name;
sprintf(c, "I have a %s", myString.c_str());
I've done everything I can to make it work and followed all of the advice I've been given, but still won't work and I don't know what's wrong.

A couple questions on the CVS, though:
How would I normally keep in sync with it?
Why would this affect my users if they get the DLL?

Posted: 29 Sep 2005, 00:25
by Fnordia
Well, you can't really use stl types across different compilers/implementations (as you have found), which is the reason why the interface itself uses standard char pointers instead of stl strings. I guess it is a bit of an oversight to still allow the interface to return structures with stl strings in them, and it should probably be changed.

Edit: Hm actually, now that I look at the file there's quite a bit of stl types used in the interface as well.. I guess these should be changed too.

Posted: 29 Sep 2005, 20:22
by AF
veylon, that isnt a very nice way fo using the interface, I myself would never do that.

Code: Select all

char c[200];
const string myString = callback->GetUnitDef("CORSOLAR").name;
sprintf(c, "I have a %s", myString.c_str()); 
should be

Code: Select all

string mystring = "I have a";
const UnitDef* ud =  callback->GetUnitDef("CORSOLAR");
mystring += ud->name.c_str();
That above should work for you. Why your string variable is 'const' or why you used '.name' when it returns a pointer not a reference, so even then ti should be ->name, aswell as the fact that the outcome of the above if ti did work would be "I have a CORSOLAR", you need to use ud->humanname instead.

Also if you cant use a string normally then that suggests you cant use a string using your wrapper class, which you have done. I think I remember you said you where using VS .JNet 2003? I'm not sure, but it always works of me. Try not to use the likes of GetUnitDef()-> etc... as you might need to change ti later on if you want extra data to be taken and you dont wanan deal with multiple calls.

Look at how strings are used in JCAI, TAI and SJ's groupAI's, they all work, even though JCAI is not 100% stable, TAI is stable though nowhere near as complete, and SJ's are all GroupAI's..

As for CVS, using tortoise CVS I just right click on the spring cvs folder I downloaded and click on update, and it does it all for me as long as I've set it up right.

Posted: 05 Oct 2005, 22:10
by Veylon
I know how I should use the interface, the issue is that it does not work!

I compiled the code for JCAI, and I got the same problems.

Fortunately, I have now made my code so that the StrDat's are optional based on a #define directive, so that those of you who think I'm mad can delete that line and all of the references to my hacked "UnitDef3.h" will instead refer to the real UnitDef.h file.

Right now I'm getting commands added to my scripting engine and making it interface with my AI. This is not my strength, so it took awhile before I got the hang of it.

I see that CVS is an online thing, and I don't have online at home, so I'll just have to do my best to keep on top any changes to CVS. I have VS 6.0 by the way, so I don't know if it is compatable with CVS anyway...

Posted: 05 Oct 2005, 22:22
by jcnossen
I think your best chance of coding in a non-hacking way ( :) ) is trying to compile the linux port on windows. You'll also be doing the linux porters a favour and speed up the process of getting a linux/win32 merge.
Once you get the linux port compiling on windows, you can write the AI on the same compiler as the spring engine itself. In that case you could just let someone else compile your AI for the VS .NET spring exe.
In any case it will take quite some time, you'll have to install boost, sdl, openal, freetype just to compile the engine.

Posted: 06 Oct 2005, 20:24
by AF
Eitherway, VS 6.0 and below dotn have the needed support to compile spring, incomplete template class support, that'll be why AI Dll's arent working and why Spring wont compile from the CVS. I would say use VS.Net2003+ or dont use VS at all for spring.