Пример #1
0
//**********************************************************************************************
// Adds an Anchor Link to an Anchor
//**********************************************************************************************
void AddAnchorLink(EERIE_BACKGROUND * eb, long anchor, long linked) 
{
	// Avoid to store Already existing Links
	for (long i = 0; i < eb->anchors[anchor].nblinked; i++)
		if (eb->anchors[anchor].linked[i] == linked) return;

	// Realloc & fill data
	eb->anchors[anchor].linked = (long *)realloc(eb->anchors[anchor].linked, sizeof(long) * (eb->anchors[anchor].nblinked + 1));

	if (!eb->anchors[anchor].linked) HERMES_Memory_Emergency_Out();

	eb->anchors[anchor].linked[eb->anchors[anchor].nblinked] = linked;
	eb->anchors[anchor].nblinked++;
}
Пример #2
0
//***********************************************************************************************
// Saves an FTL File
// Must pass the original name of the theo file
//-----------------------------------------------------------------------------------------------
// VERIFIED (Cyril 2001/10/15)
//***********************************************************************************************
bool ARX_FTL_Save(const char * file, EERIE_3DOBJ * obj)
{
	// Need an object to be saved !
	if (obj == NULL) return false;

	// Generate File name/path and create it
	char path[256];
	char gamefic[256];
	sprintf(gamefic, "Game\\%s", file);
	SetExt(gamefic, ".FTL");
	strcpy(path, gamefic);
	RemoveName(path);

	if (!CreateFullPath(path)) return NULL;

	// create some usefull vars
	ARX_FTL_PRIMARY_HEADER 	*		afph;
	ARX_FTL_SECONDARY_HEADER 	*		afsh;
	ARX_FTL_CLOTHES_DATA_HEADER 	*	afcdh;
	ARX_FTL_3D_DATA_HEADER 	*		af3Ddh;
	ARX_FTL_COLLISION_SPHERES_DATA_HEADER 	*		afcsdh;
	unsigned char * dat = NULL;
	long pos = 0;
	long allocsize = 8000000; // need to compute it more precisely

	// Compute allocsize...
	allocsize =	sizeof(ARX_FTL_PRIMARY_HEADER)
	            +	512 //checksum
	            +	sizeof(ARX_FTL_SECONDARY_HEADER)
	            +	sizeof(ARX_FTL_3D_DATA_HEADER)
	            +	sizeof(EERIE_OLD_VERTEX) * obj->nbvertex

	            +	sizeof(EERIE_FACE_FTL) * obj->nbfaces
	            +	obj->nbmaps * 256	// texturecontainernames
	            +	sizeof(EERIE_ACTIONLIST) * obj->nbaction
	            +	128000; // just in case...

	if (obj->nbgroups > 0)
	{
		allocsize += sizeof(EERIE_GROUPLIST) * obj->nbgroups;

		for (long i = 0; i < obj->nbgroups; i++)
		{
			if (obj->grouplist[i].nb_index > 0)
			{
				allocsize += sizeof(long) * obj->grouplist[i].nb_index;
			}
		}
	}

	if (obj->nbselections > 0)
	{
		allocsize += sizeof(EERIE_SELECTIONS) * obj->nbselections;

		for (long i = 0; i < obj->nbselections; i++)
		{
			allocsize += sizeof(long) * obj->selections[i].nb_selected;
		}
	}

	if (obj->sdata && obj->sdata->nb_spheres) // Collision Spheres Data
	{
		allocsize += sizeof(ARX_FTL_COLLISION_SPHERES_DATA_HEADER);
		allocsize += sizeof(COLLISION_SPHERE) * obj->sdata->nb_spheres;
	}

	if (obj->cdata) // Clothes DATA
	{
		allocsize += sizeof(ARX_FTL_CLOTHES_DATA_HEADER);
		allocsize += sizeof(CLOTHESVERTEX) * obj->cdata->nb_cvert;
		allocsize += sizeof(EERIE_SPRINGS) * obj->cdata->nb_springs;
	}

	// Finished computing allocsize Now allocate it...
	dat = (unsigned char *)malloc(allocsize);

	if (!dat)
		HERMES_Memory_Emergency_Out();

	memset(dat, 0, allocsize);

	// Primary Header
	afph = (ARX_FTL_PRIMARY_HEADER *)dat;
	pos += sizeof(ARX_FTL_PRIMARY_HEADER);

	if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");

	afph->ident[0] = 'F';
	afph->ident[1] = 'T';
	afph->ident[2] = 'L';
	afph->version = CURRENT_FTL_VERSION;

	// Identification
	char check[512];
	
	HERMES_CreateFileCheck(file, check, 512, CURRENT_FTL_VERSION);
	memcpy(dat + pos, check, 512);
	pos += 512;

	if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");

	// Secondary Header
	afsh = (ARX_FTL_SECONDARY_HEADER *)(dat + pos);
	pos += sizeof(ARX_FTL_SECONDARY_HEADER);

	if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");

	// 3D Data
	afsh->offset_3Ddata = pos; //-1;
	af3Ddh = (ARX_FTL_3D_DATA_HEADER *)(dat + afsh->offset_3Ddata);
	pos += sizeof(ARX_FTL_3D_DATA_HEADER);

	if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");

	af3Ddh->nb_vertex = obj->nbvertex;
	af3Ddh->nb_faces = obj->nbfaces;
	af3Ddh->nb_maps = obj->nbmaps;
	af3Ddh->nb_groups = obj->nbgroups;
	af3Ddh->nb_action = obj->nbaction;
	af3Ddh->nb_selections = obj->nbselections;
	af3Ddh->origin = obj->origin;

	// vertexes
	if (af3Ddh->nb_vertex > 0)
	{
		for (long ii = 0; ii < af3Ddh->nb_vertex; ii++)
		{
			memcpy(dat + pos, &obj->vertexlist[ii], sizeof(EERIE_OLD_VERTEX));
			pos += sizeof(EERIE_OLD_VERTEX);
		}

		if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
	}

	// faces
	if (af3Ddh->nb_faces > 0)
	{
		for (long ii = 0; ii < af3Ddh->nb_faces; ii++)
		{
			EERIE_FACE_FTL * eff = (EERIE_FACE_FTL *)(dat + pos);
			eff->facetype = obj->facelist[ii].facetype;
			eff->texid = obj->facelist[ii].texid;
			eff->transval = obj->facelist[ii].transval;
			eff->temp = obj->facelist[ii].temp;
			memcpy(&eff->norm, &obj->facelist[ii].norm, sizeof(EERIE_3D));

			for (long kk = 0; kk < IOPOLYVERT; kk++)
			{
				memcpy(&eff->nrmls[kk], &obj->facelist[ii].nrmls[kk], sizeof(EERIE_3D));
				eff->vid[kk] = obj->facelist[ii].vid[kk];
				eff->u[kk] = obj->facelist[ii].u[kk];
				eff->v[kk] = obj->facelist[ii].v[kk];
				eff->ou[kk] = obj->facelist[ii].ou[kk];
				eff->ov[kk] = obj->facelist[ii].ov[kk];
				eff->rgb[kk] = 0; 
			}

			pos += sizeof(EERIE_FACE_FTL); 
			if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
		}
	}

	// textures
	for (long i = 0; i < af3Ddh->nb_maps; i++)
	{
		char ficc[256];
		memset(ficc, 0, 256);

		if (obj->texturecontainer[i])
			strcpy(ficc, obj->texturecontainer[i]->m_texName);

		memcpy(dat + pos, ficc, 256);
		pos += 256;

		if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
	}

	// groups
	if (af3Ddh->nb_groups > 0)
	{
		memcpy(dat + pos, obj->grouplist, sizeof(EERIE_GROUPLIST)*af3Ddh->nb_groups);
		pos += sizeof(EERIE_GROUPLIST) * af3Ddh->nb_groups;

		if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");

		for (int i = 0; i < af3Ddh->nb_groups; i++)
		{
			if (obj->grouplist[i].nb_index > 0)
			{
				memcpy(dat + pos, obj->grouplist[i].indexes, sizeof(long)*obj->grouplist[i].nb_index);
				pos += sizeof(long) * obj->grouplist[i].nb_index;

				if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
			}
		}
	}


	// actionpoints
	if (af3Ddh->nb_action > 0)
	{
		memcpy(dat + pos, obj->actionlist, sizeof(EERIE_ACTIONLIST)*af3Ddh->nb_action);
		pos += sizeof(EERIE_ACTIONLIST) * af3Ddh->nb_action;

		if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
	}

	// selections
	if (af3Ddh->nb_selections > 0)
	{
		memcpy(dat + pos, obj->selections, sizeof(EERIE_SELECTIONS)*af3Ddh->nb_selections);
		pos += sizeof(EERIE_SELECTIONS) * af3Ddh->nb_selections;

		if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");

		for (int i = 0; i < af3Ddh->nb_selections; i++)
		{
			memcpy(dat + pos, obj->selections[i].selected, sizeof(long)*obj->selections[i].nb_selected);
			pos += sizeof(long) * obj->selections[i].nb_selected;

			if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
		}

		strcpy(af3Ddh->name, obj->file);
	}

	// Progressive DATA
	afsh->offset_progressive_data = -1;
	

	// Collision Spheres Data
	if (obj->sdata && obj->sdata->nb_spheres)
	{
		afsh->offset_collision_spheres = pos; //-1;
		afcsdh = (ARX_FTL_COLLISION_SPHERES_DATA_HEADER *)(dat + afsh->offset_collision_spheres);
		pos += sizeof(ARX_FTL_COLLISION_SPHERES_DATA_HEADER);

		if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");

		afcsdh->nb_spheres = obj->sdata->nb_spheres;

		memcpy(dat + pos, obj->sdata->spheres, sizeof(COLLISION_SPHERE)*obj->sdata->nb_spheres);
		pos += sizeof(COLLISION_SPHERE) * obj->sdata->nb_spheres;

		if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
	}
	else afsh->offset_collision_spheres = -1;


	// Clothes DATA
	if (obj->cdata == NULL)
	{
		afsh->offset_clothes_data = -1;
	}
	else
	{
		afsh->offset_clothes_data = pos;
		afcdh = (ARX_FTL_CLOTHES_DATA_HEADER *)(dat + afsh->offset_clothes_data);

		afcdh->nb_cvert = obj->cdata->nb_cvert;
		afcdh->nb_springs = obj->cdata->nb_springs;
		pos += sizeof(ARX_FTL_CLOTHES_DATA_HEADER);

		if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");

		// now save cvert
		memcpy(dat + pos, obj->cdata->cvert, sizeof(CLOTHESVERTEX)*obj->cdata->nb_cvert);
		pos += sizeof(CLOTHESVERTEX) * obj->cdata->nb_cvert;

		if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");

		// now saves springs
		memcpy(dat + pos, obj->cdata->springs, sizeof(EERIE_SPRINGS)*obj->cdata->nb_springs);
		pos += sizeof(EERIE_SPRINGS) * obj->cdata->nb_springs;

		if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
	}

	afsh->offset_physics_box = -1;

	afsh->offset_cylinder = -1;

	// Now we can flush our cool FTL file to the hard drive
	FileHandle handle;
	char _error[512];

	if (pos > allocsize)
	{
		sprintf(_error, "Badly Allocated SaveBuffer...%s", gamefic);
		goto error;
	}

	char * compressed;
	compressed = NULL;
	long cpr_pos;
	cpr_pos = 0;
	LogError <<"IMPLODE NOT IMPLEMENTED";
	// TODO fix
	//compressed = STD_Implode((char *)dat, pos, &cpr_pos);

	// Now Saving Whole Buffer
	if (!(handle = FileOpenWrite(gamefic)))
	{
		sprintf(_error, "Unable to Open %s for Write...", gamefic);
		goto error;
	}

	if (FileWrite(handle, compressed, cpr_pos) != cpr_pos)
	{
		sprintf(_error, "Unable to Write to %s", gamefic);
		goto error;
	}

	FileCloseWrite(handle);
	free(compressed);
	free(dat);
	return true;

error:
	;
	ShowPopup(_error);
	free(dat);

	return false;
}
Пример #3
0
bool AddAnchor_Original_Method(EERIE_BACKGROUND * eb, EERIE_BKG_INFO * eg, EERIE_3D * pos, long flags)
{
	long found = 0;
	long best = 0;
	long stop_radius = 0;
	float best_dist = 99999999999.f;
	float v_dist = 99999999999.f;

	EERIE_CYLINDER testcyl;
	EERIE_CYLINDER currcyl;
	EERIE_CYLINDER bestcyl;

	bestcyl.height = 0;
	bestcyl.radius = 0;

	
	for (long rad = 0; rad < 20; rad += 10) 
		for (long ang = 0; ang < 360; ang += 45) // 45
		{
			float t = DEG2RAD((float)ang);
			// We set our current position depending on given position, radius & angle.
			currcyl.radius = 40; 
			currcyl.height = -165; 
			currcyl.origin.x = pos->x - EEsin(t) * (float)rad;
			currcyl.origin.y = pos->y;
			currcyl.origin.z = pos->z + EEcos(t) * (float)rad;

			stop_radius = 0;
			found = 0;
			long climb = 0;

			while ((stop_radius != 1))
			{
				memcpy(&testcyl, &currcyl, sizeof(EERIE_CYLINDER));
				testcyl.radius += INC_RADIUS;

				if (ANCHOR_AttemptValidCylinderPos(&testcyl, NULL, CFLAG_NO_INTERCOL | CFLAG_EXTRA_PRECISION | CFLAG_ANCHOR_GENERATION))
				{
					memcpy(&currcyl, &testcyl, sizeof(EERIE_CYLINDER));
					found = 1;
				}
				else
				{
					if ((testcyl.origin.y != currcyl.origin.y)
					        && (EEfabs(testcyl.origin.y - pos->y) < 50))
					{
						testcyl.radius -= INC_RADIUS;
						memcpy(&currcyl, &testcyl, sizeof(EERIE_CYLINDER));
						climb++;
					}
					else
						stop_radius = 1;
				}

				if (climb > 4) stop_radius = 1;

				if (currcyl.radius >= 50.f) stop_radius = 1;
			}

			if (found)
			{
				float dist = TRUEEEDistance3D(pos, &currcyl.origin);
				float vd = EEfabs(pos->y - currcyl.origin.y);

				if (currcyl.radius >= bestcyl.radius)	
				{
					if (((best_dist > dist) && (currcyl.radius == bestcyl.radius))
					        || (currcyl.radius > bestcyl.radius))
					{
						memcpy(&bestcyl, &currcyl, sizeof(EERIE_CYLINDER));
						best_dist = dist;
						v_dist = vd;
						best = 1;
					}
				}
			}
		}

	if (!best) return FALSE;

	if (CylinderAboveInvalidZone(&bestcyl)) return FALSE;

	if (flags == MUST_BE_BIG)
	{
		if (bestcyl.radius < 60) return FALSE;
	}

	// avoid to recreate same anchor twice...
	if (0)
		for (long k = 0; k < eb->nbanchors; k++)
		{
			_ANCHOR_DATA * ad = &eb->anchors[k];

			if ((ad->pos.x == bestcyl.origin.x)
			        &&	(ad->pos.y == bestcyl.origin.y)
			        &&	(ad->pos.z == bestcyl.origin.z))
			{
				if (ad->radius >= bestcyl.radius)
					return FALSE;

				if (ad->radius <= bestcyl.radius)
				{
					ad->height = bestcyl.height;
					ad->radius = bestcyl.radius;
					return FALSE;
				}
			}
		}

	eg->ianchors = (long *)realloc(eg->ianchors, sizeof(long) * (eg->nbianchors + 1));

	if (!eg->ianchors) HERMES_Memory_Emergency_Out();

	eg->ianchors[eg->nbianchors] = eb->nbanchors;
	eg->nbianchors++;

	eb->anchors = (_ANCHOR_DATA *)realloc(eb->anchors, sizeof(_ANCHOR_DATA) * (eb->nbanchors + 1));

	if (!eb->anchors) HERMES_Memory_Emergency_Out();

	_ANCHOR_DATA * ad = &eb->anchors[eb->nbanchors];
	ad->pos.x = bestcyl.origin.x; 
	ad->pos.y = bestcyl.origin.y; 
	ad->pos.z = bestcyl.origin.z; 
	ad->height = bestcyl.height; 
	ad->radius = bestcyl.radius; 
	ad->linked = NULL;
	ad->nblinked = 0;
	ad->flags = 0;
	eb->nbanchors++;
	return TRUE;
}
Пример #4
0
bool DirectAddAnchor_Original_Method(EERIE_BACKGROUND * eb, EERIE_BKG_INFO * eg, EERIE_3D * pos, long flags)
{
	long found = 0;
	long best = 0;
	long stop_radius = 0;
	float best_dist = 99999999999.f;
	float v_dist = 99999999999.f;

	EERIE_CYLINDER testcyl;
	EERIE_CYLINDER currcyl;
	EERIE_CYLINDER bestcyl;

	bestcyl.height = 0;
	bestcyl.radius = 0;
	currcyl.radius = 40;
	currcyl.height = -165.f;
	currcyl.origin.x = pos->x;
	currcyl.origin.y = pos->y;
	currcyl.origin.z = pos->z;

	stop_radius = 0;
	found = 0;
	long climb = 0;

	while (stop_radius != 1)
	{
		memcpy(&testcyl, &currcyl, sizeof(EERIE_CYLINDER));
		testcyl.radius += INC_RADIUS;

		if (ANCHOR_AttemptValidCylinderPos(&testcyl, NULL, CFLAG_NO_INTERCOL | CFLAG_EXTRA_PRECISION | CFLAG_ANCHOR_GENERATION))
		{
			memcpy(&currcyl, &testcyl, sizeof(EERIE_CYLINDER));
			found = 1;
		}
		else
		{
			if ((testcyl.origin.y != currcyl.origin.y)
			        && (EEfabs(testcyl.origin.y - pos->y) < 50))
			{
				testcyl.radius -= INC_RADIUS;
				memcpy(&currcyl, &testcyl, sizeof(EERIE_CYLINDER));
				climb++;
			}
			else
				stop_radius = 1;
		}

		if (climb > 4) stop_radius = 1;

		if (currcyl.radius >= 50.f) stop_radius = 1;

	}

	if (found)
	{
		float dist = TRUEEEDistance3D(pos, &currcyl.origin);
		float vd = EEfabs(pos->y - currcyl.origin.y);

		if ((currcyl.radius >= bestcyl.radius))
		{
			if (((best_dist > dist) && (currcyl.radius == bestcyl.radius))
			        || (currcyl.radius > bestcyl.radius))
			{
				memcpy(&bestcyl, &currcyl, sizeof(EERIE_CYLINDER));
				best_dist = dist;
				v_dist = vd;
				best = 1;
			}
		}
	}

	if (!best) return FALSE;

	if (CylinderAboveInvalidZone(&bestcyl)) return FALSE;

	for (long k = 0; k < eb->nbanchors; k++)
	{
		_ANCHOR_DATA * ad = &eb->anchors[k];

		if (TRUEEEDistance3D(&ad->pos, &bestcyl.origin) < 50.f) return FALSE;

		if (TRUEDistance2D(ad->pos.x, ad->pos.z, bestcyl.origin.x, bestcyl.origin.z) < 45.f)
		{
			if (EEfabs(ad->pos.y - bestcyl.origin.y) < 90.f) return FALSE;

			EERIEPOLY * ep = ANCHOR_CheckInPolyPrecis(ad->pos.x, ad->pos.y, ad->pos.z);
			EERIEPOLY * ep2 = ANCHOR_CheckInPolyPrecis(ad->pos.x, bestcyl.origin.y, ad->pos.z);

			if (ep2 == ep) return FALSE;
		}

	}

	eg->ianchors = (long *)realloc(eg->ianchors, sizeof(long) * (eg->nbianchors + 1));

	if (!eg->ianchors) HERMES_Memory_Emergency_Out();

	eg->ianchors[eg->nbianchors] = eb->nbanchors;
	eg->nbianchors++;

	eb->anchors = (_ANCHOR_DATA *)realloc(eb->anchors, sizeof(_ANCHOR_DATA) * (eb->nbanchors + 1));

	if (!eb->anchors) HERMES_Memory_Emergency_Out();

	_ANCHOR_DATA * ad = &eb->anchors[eb->nbanchors];
	ad->pos.x = bestcyl.origin.x; 
	ad->pos.y = bestcyl.origin.y;
	ad->pos.z = bestcyl.origin.z; 
	ad->height = bestcyl.height; 
	ad->radius = bestcyl.radius; 
	ad->linked = NULL;
	ad->nblinked = 0;
	ad->flags = 0;
	eb->nbanchors++;
	return TRUE;
}