2025-07-18 21:43 CEST

View Issue Details Jump to Notes ]
IDProjectCategoryView StatusLast Update
0000224Spring engineGeneralpublic2006-08-05 00:17
ReporterSean Mirrsen 
Assigned To 
PrioritynormalSeverityfeatureReproducibilityalways
StatusclosedResolutionfixed 
Product Version 
Target VersionFixed in Version 
Summary0000224: [patch] Rotating Buildings
DescriptionThis allows to orient the buildings you place before construction in 90 degree increments. It still might have various quirks, such as AI incompatibility or net desync (couldn't test), and the code is somewhat bulky at places, but it works fine. Also, I couldn't find how to make the patch have relative filenames instead of absolute, so another patch will occur if this one's unusable.
Additional InformationYou have to add "bind '<' spinbuilddir" and "bind '>' unspinbuilddir" to uikeys.txt for the feature to work.
TagsNo tags attached.
Checked infolog.txt for Errors
Attached Files
  • diff file icon Rotating Buildings.diff (44,086 bytes) 2006-07-01 22:47 -
    Index: C:/Springproject/rts/ExternalAI/AICallback.cpp
    ===================================================================
    --- C:/Springproject/rts/ExternalAI/AICallback.cpp	(revision 1559)
    +++ C:/Springproject/rts/ExternalAI/AICallback.cpp	(working copy)
    @@ -604,7 +604,7 @@
     {
     	CFeature* f;
     	pos=helper->Pos2BuildPos (pos, unitDef);
    -	return !!uh->TestUnitBuildSquare(pos,unitDef->name,f);
    +	return !!uh->TestUnitBuildSquare(pos,unitDef->name,f,0);
     }
     
     
    @@ -656,7 +656,7 @@
     		float z = pos.z+ofs[so].dy*SQUARE_SIZE*2;
     		float3 p(x,0,z);
     		p = helper->Pos2BuildPos (p, unitdef);
    -		if(uh->TestUnitBuildSquare(p,unitdef,feature) && (!feature || feature->allyteam!=allyteam))
    +		if(uh->TestUnitBuildSquare(p,unitdef,feature,0) && (!feature || feature->allyteam!=allyteam))
     		{
     			int xs=(int)(x/SQUARE_SIZE);
     			int zs=(int)(z/SQUARE_SIZE);
    Index: C:/Springproject/rts/Game/Game.cpp
    ===================================================================
    --- C:/Springproject/rts/Game/Game.cpp	(revision 1559)
    +++ C:/Springproject/rts/Game/Game.cpp	(working copy)
    @@ -592,6 +592,48 @@
     	if (s=="updatefov")
     		gd->updateFov=!gd->updateFov;
     
    +	if (s=="spinbuilddir"){
    +		switch(guihandler->buildFacing){
    +			case 0:
    +				guihandler->buildFacing=1;
    +				info->AddLine("Buildings set to face East");
    +				break;
    +			case 1:
    +				guihandler->buildFacing=2;
    +				info->AddLine("Buildings set to face North");
    +					break;
    +			case 2:
    +				guihandler->buildFacing=3;
    +				info->AddLine("Buildings set to face West");
    +					break;
    +			case 3:
    +				guihandler->buildFacing=0;
    +				info->AddLine("Buildings set to face South");
    +					break;
    +		}
    +	}
    +
    +	if (s=="unspinbuilddir"){
    +		switch(guihandler->buildFacing){
    +			case 0:
    +				guihandler->buildFacing=3;
    +				info->AddLine("Buildings set to face West");
    +				break;
    +			case 1:
    +				guihandler->buildFacing=0;
    +				info->AddLine("Buildings set to face South");
    +					break;
    +			case 2:
    +				guihandler->buildFacing=1;
    +				info->AddLine("Buildings set to face East");
    +					break;
    +			case 3:
    +				guihandler->buildFacing=2;
    +				info->AddLine("Buildings set to face North");
    +					break;
    +		}
    +	}
    +
     	if (s=="drawtrees")
     		treeDrawer->drawTrees=!treeDrawer->drawTrees;
     
    @@ -879,6 +921,26 @@
     		inMapDrawer->keyPressed=false;
     	}
     
    +	if(s=="buildfaceup"){
    +				guihandler->buildFacing=0;
    +				info->AddLine("Buildings set to face South");
    +	}
    +
    +	if(s=="buildfaceright"){
    +				guihandler->buildFacing=3;
    +				info->AddLine("Buildings set to face West");
    +	}
    +
    +	if(s=="buildfacedown"){
    +				guihandler->buildFacing=2;
    +				info->AddLine("Buildings set to face North");
    +	}
    +
    +	if(s=="buildfaceleft"){
    +				guihandler->buildFacing=1;
    +				info->AddLine("Buildings set to face East");
    +	}
    +
     	if (s=="moveforward")
     		camMove[0]=false;
     
    Index: C:/Springproject/rts/Game/GameHelper.cpp
    ===================================================================
    --- C:/Springproject/rts/Game/GameHelper.cpp	(revision 1559)
    +++ C:/Springproject/rts/Game/GameHelper.cpp	(working copy)
    @@ -611,9 +611,34 @@
     	}
     }
     
    -float3 CGameHelper::Pos2BuildPos(float3 pos, const UnitDef* ud)
    +float3 CGameHelper::Pos2BuildPos(float3 pos, const UnitDef* ud, int facing)
     {
    -	if(ud->xsize&2)
    +	int xsize=1;
    +	int ysize=1;
    +			switch (facing)
    +			{
    +			case 0:
    +				xsize=ud->rxsize;
    +                ysize=ud->rysize;
    +				break;
    +			case 1:
    +				xsize=ud->rysize;
    +                ysize=ud->rxsize;
    +				break;
    +			case 2:
    +				xsize=ud->rxsize;
    +                ysize=ud->rysize;
    +				break;
    +			case 3:
    +				xsize=ud->rysize;
    +                ysize=ud->rxsize;
    +				break;
    +			default:
    +				xsize=ud->rxsize;
    +                ysize=ud->rysize;
    +			}
    +
    +	if(xsize&2)
     		pos.x=floor((pos.x)/(SQUARE_SIZE*2))*SQUARE_SIZE*2+8;
     	else
     		pos.x=floor((pos.x+8)/(SQUARE_SIZE*2))*SQUARE_SIZE*2;
    @@ -618,7 +643,7 @@
     	else
     		pos.x=floor((pos.x+8)/(SQUARE_SIZE*2))*SQUARE_SIZE*2;
     
    -	if(ud->ysize&2)
    +	if(ysize&2)
     		pos.z=floor((pos.z)/(SQUARE_SIZE*2))*SQUARE_SIZE*2+8;
     	else
     		pos.z=floor((pos.z+8)/(SQUARE_SIZE*2))*SQUARE_SIZE*2;
    Index: C:/Springproject/rts/Game/GameHelper.h
    ===================================================================
    --- C:/Springproject/rts/Game/GameHelper.h	(revision 1559)
    +++ C:/Springproject/rts/Game/GameHelper.h	(working copy)
    @@ -44,7 +44,7 @@
     	void Explosion(float3 pos,const DamageArray& damages,float radius,CUnit* owner,bool damageGround=true,float gfxMod=1,bool ignoreOwner=false,CExplosionGenerator *explosionGraphics=0);
     	float TraceRayTeam(const float3& start,const float3& dir,float length, CUnit*& hit,bool useRadar,CUnit* exclude,int allyteam);
     	void BuggerOff(float3 pos, float radius,CUnit* exclude=0);
    -	float3 Pos2BuildPos(float3 pos, const UnitDef* ud);
    +	float3 Pos2BuildPos(float3 pos, const UnitDef* ud, int facing=0);
     	void Update(void);
     
     	bool LineFeatureCol(const float3& start, const float3& dir,float length);
    Index: C:/Springproject/rts/Game/UI/GUI/GUIgame.cpp
    ===================================================================
    --- C:/Springproject/rts/Game/UI/GUI/GUIgame.cpp	(revision 1559)
    +++ C:/Springproject/rts/Game/UI/GUI/GUIgame.cpp	(working copy)
    @@ -407,7 +407,7 @@
     						int size=positions.size();
     						for(int i=0; i<size; i++)
     						{
    -							if(uh->ShowUnitBuildSquare(positions[i],unitdef))
    +							if(uh->ShowUnitBuildSquare(positions[i],unitdef, guihandler->buildFacing))
     								glColor4f(0.7,1,1,0.4);
     							else
     								glColor4f(1,0.5,0.5,0.4);
    @@ -439,7 +439,7 @@
     					}
     					else
     					{
    -						if(uh->ShowUnitBuildSquare(pos,unitdef))
    +						if(uh->ShowUnitBuildSquare(pos,unitdef,guihandler->buildFacing))
     							glColor4f(0.7,1,1,0.4);
     						else
     							glColor4f(1,0.5,0.5,0.4);
    Index: C:/Springproject/rts/Game/UI/GuiHandler.cpp
    ===================================================================
    --- C:/Springproject/rts/Game/UI/GuiHandler.cpp	(revision 1559)
    +++ C:/Springproject/rts/Game/UI/GuiHandler.cpp	(working copy)
    @@ -96,7 +96,8 @@
     	activePage(0),
     	maxPages(0),
     	showingMetal(false),
    -	buildSpacing(0)
    +	buildSpacing(0),
    +	buildFacing(0)
     {
     //	LoadCMDBitmap(CMD_STOP, "bitmaps\\ocean.bmp");
     	LoadCMDBitmap(CMD_STOCKPILE, "bitmaps/armsilo1.bmp");
    @@ -735,7 +736,7 @@
     							}
     						}
     					}
    -					if(uh->ShowUnitBuildSquare(pos,unitdef,cv))
    +					if(uh->ShowUnitBuildSquare(pos,unitdef,cv,buildFacing))
     						glColor4f(0.7,1,1,0.4);
     					else
     						glColor4f(1,0.5,0.5,0.4);
    @@ -740,7 +741,7 @@
     					else
     						glColor4f(1,0.5,0.5,0.4);
     
    -					unitDrawer->DrawBuildingSample(unitdef, gu->myTeam, pos);
    +					unitDrawer->DrawBuildingSample(unitdef, gu->myTeam, pos, buildFacing);
     					if(unitdef->weapons.size()>0){	//draw range
     						glDisable(GL_TEXTURE_2D);
     						glColor4f(1,0.3,0.3,0.7);
    @@ -1152,6 +1153,7 @@
     			if(!unitdef){
     				return defaultRet;
     			}
    +
     			float3 pos=camera->pos+mouse->dir*dist;
     			std::vector<float3> buildPos;
     			if(keys[SDLK_LSHIFT] && button==SDL_BUTTON_LEFT){
    @@ -1175,6 +1177,7 @@
     				c.params.push_back(pos.x);
     				c.params.push_back(pos.y);
     				c.params.push_back(pos.z);
    +				c.params.push_back(buildFacing);
     				CreateOptions(c,(button==SDL_BUTTON_LEFT?0:1));
     				if(!preview)
     					selectedUnits.GiveCommand(c);
    @@ -1185,6 +1188,7 @@
     			c.params.push_back(pos.x);
     			c.params.push_back(pos.y);
     			c.params.push_back(pos.z);
    +			c.params.push_back(buildFacing);
     			CreateOptions(c,(button==SDL_BUTTON_LEFT?0:1));
     			return c;}
     
    @@ -1319,8 +1323,30 @@
     {
     	std::vector<float3> ret;
     
    -	start=helper->Pos2BuildPos(start,unitdef);
    -	end=helper->Pos2BuildPos(end,unitdef);
    +	start=helper->Pos2BuildPos(start,unitdef,buildFacing);
    +	end=helper->Pos2BuildPos(end,unitdef,buildFacing);
    +	int tmp_xsize1=1;	//This thing is lotsa HAX. I don't think I imagine a more bulky way of doing this.
    +	int tmp_xsize2=1;
    +	int tmp_ysize1=1;
    +	int tmp_ysize2=1;
    +
    +	switch(buildFacing){
    +		case 0:
    +			tmp_xsize1=unitdef->rxsize;
    +			tmp_ysize1=unitdef->rysize;
    +			break;
    +		case 1:
    +			tmp_xsize1=unitdef->rysize;
    +			tmp_ysize1=unitdef->rxsize;
    +			break;
    +		case 2:
    +			tmp_xsize1=unitdef->rxsize;
    +			tmp_ysize1=unitdef->rysize;
    +			break;
    +		case 3:
    +			tmp_xsize1=unitdef->rysize;
    +			tmp_ysize1=unitdef->rxsize;
    +			break;}
     
     	float3 buildPos;
     	UnitDef* unitdef2=0;
    @@ -1340,6 +1366,26 @@
     			}
     		}
     	}
    +	if(unitdef2){
    +	switch(buildFacing){
    +		case 0:
    +			tmp_xsize2=unitdef2->rxsize;
    +			tmp_ysize2=unitdef2->rysize;
    +			break;
    +		case 1:
    +			tmp_xsize2=unitdef2->rysize;
    +			tmp_ysize2=unitdef2->rxsize;
    +			break;
    +		case 2:
    +			tmp_xsize2=unitdef2->rxsize;
    +			tmp_ysize2=unitdef2->rysize;
    +			break;
    +		case 3:
    +			tmp_xsize2=unitdef2->rysize;
    +			tmp_ysize2=unitdef2->rxsize;
    +			break;}
    +	}
    +
     	if(unitdef2 && keys[SDLK_LSHIFT] && keys[SDLK_LCTRL]){		//circle build around building
     		Command c;
     		c.id = -unitdef->id;
    @@ -1348,13 +1394,13 @@
     		c.params.push_back(0);
     
     		float3 pos2 = buildPos;
    -		pos2=helper->Pos2BuildPos(pos2,unitdef2);
    +		pos2=helper->Pos2BuildPos(pos2,unitdef2,buildFacing);
     		start=pos2;
     		end=pos2;
    -		start.x-=(unitdef2->xsize/2)*SQUARE_SIZE;
    -		start.z-=(unitdef2->ysize/2)*SQUARE_SIZE;
    -		end.x+=(unitdef2->xsize/2)*SQUARE_SIZE;
    -		end.z+=(unitdef2->ysize/2)*SQUARE_SIZE;
    +		start.x-=(tmp_xsize2/2)*SQUARE_SIZE;
    +		start.z-=(tmp_ysize2/2)*SQUARE_SIZE;
    +		end.x+=(tmp_xsize2/2)*SQUARE_SIZE;
    +		end.z+=(tmp_ysize2/2)*SQUARE_SIZE;
     		
     		float3 pos=start;
     		for(;pos.x<=end.x;pos.x+=unitdef->xsize*SQUARE_SIZE){
    @@ -1359,9 +1405,9 @@
     		float3 pos=start;
     		for(;pos.x<=end.x;pos.x+=unitdef->xsize*SQUARE_SIZE){
     			float3 p2=pos;
    -			p2.x+=(unitdef->xsize/2)*SQUARE_SIZE;
    -			p2.z-=(unitdef->ysize/2)*SQUARE_SIZE;
    -			p2=helper->Pos2BuildPos(p2,unitdef);
    +			p2.x+=(tmp_xsize1/2)*SQUARE_SIZE;
    +			p2.z-=(tmp_ysize1/2)*SQUARE_SIZE;
    +			p2=helper->Pos2BuildPos(p2,unitdef,buildFacing);
     			c.params[0] = p2.x;
     			c.params[1] = p2.y;
     			c.params[2] = p2.z;
    @@ -1378,11 +1424,11 @@
     		}
     		pos=start;
     		pos.x=end.x;
    -		for(;pos.z<=end.z;pos.z+=unitdef->ysize*SQUARE_SIZE){
    +		for(;pos.z<=end.z;pos.z+=tmp_ysize1*SQUARE_SIZE){
     			float3 p2=pos;
    -			p2.x+=(unitdef->xsize/2)*SQUARE_SIZE;
    -			p2.z+=(unitdef->ysize/2)*SQUARE_SIZE;
    -			p2=helper->Pos2BuildPos(p2,unitdef);
    +			p2.x+=(tmp_xsize1/2)*SQUARE_SIZE;
    +			p2.z+=(tmp_ysize1/2)*SQUARE_SIZE;
    +			p2=helper->Pos2BuildPos(p2,unitdef,buildFacing);
     			c.params[0] = p2.x;
     			c.params[1] = p2.y;
     			c.params[2] = p2.z;
    @@ -1398,11 +1444,11 @@
     			}
     		}
     		pos=end;
    -		for(;pos.x>=start.x;pos.x-=unitdef->xsize*SQUARE_SIZE){
    +		for(;pos.x>=start.x;pos.x-=tmp_xsize1*SQUARE_SIZE){
     			float3 p2=pos;
    -			p2.x-=(unitdef->xsize/2)*SQUARE_SIZE;
    -			p2.z+=(unitdef->ysize/2)*SQUARE_SIZE;
    -			p2=helper->Pos2BuildPos(p2,unitdef);
    +			p2.x-=(tmp_xsize1/2)*SQUARE_SIZE;
    +			p2.z+=(tmp_ysize1/2)*SQUARE_SIZE;
    +			p2=helper->Pos2BuildPos(p2,unitdef,buildFacing);
     			c.params[0] = p2.x;
     			c.params[1] = p2.y;
     			c.params[2] = p2.z;
    @@ -1419,11 +1465,11 @@
     		}
     		pos=end;
     		pos.x=start.x;
    -		for(;pos.z>=start.z;pos.z-=unitdef->ysize*SQUARE_SIZE){
    +		for(;pos.z>=start.z;pos.z-=tmp_ysize1*SQUARE_SIZE){
     			float3 p2=pos;
    -			p2.x-=(unitdef->xsize/2)*SQUARE_SIZE;
    -			p2.z-=(unitdef->ysize/2)*SQUARE_SIZE;
    -			p2=helper->Pos2BuildPos(p2,unitdef);
    +			p2.x-=(tmp_xsize1/2)*SQUARE_SIZE;
    +			p2.z-=(tmp_ysize1/2)*SQUARE_SIZE;
    +			p2=helper->Pos2BuildPos(p2,unitdef,buildFacing);
     			c.params[0] = p2.x;
     			c.params[1] = p2.y;
     			c.params[2] = p2.z;
    @@ -1439,7 +1485,7 @@
     			}
     		}
     	} else if(keys[SDLK_LALT]){			//build a rectangle
    -		float xsize=unitdef->xsize*8+buildSpacing*16;
    +		float xsize=tmp_xsize1*8+buildSpacing*16;
     		int xnum=(int)((fabs(end.x-start.x)+xsize*1.4)/xsize);
     		int xstep=(int)xsize;
     		if(start.x>end.x)
    @@ -1445,7 +1491,7 @@
     		if(start.x>end.x)
     			xstep*=-1;
     
    -		float zsize=unitdef->ysize*8+buildSpacing*16;
    +		float zsize=tmp_ysize1*8+buildSpacing*16;
     		int znum=(int)((fabs(end.z-start.z)+zsize*1.4)/zsize);
     		int zstep=(int)zsize;
     		if(start.z>end.z)
    @@ -1457,7 +1503,7 @@
     			for(float x=start.x;xn<xnum;++xn){
     				if(!keys[SDLK_LCTRL] || zn==0 || xn==0 || zn==znum-1 || xn==xnum-1){
     					float3 pos(x,0,z);
    -					pos=helper->Pos2BuildPos(pos,unitdef);
    +					pos=helper->Pos2BuildPos(pos,unitdef,buildFacing);
     					ret.push_back(pos);
     				}
     				x+=xstep;
    @@ -1466,7 +1512,7 @@
     		}
     	} else {			//build a line
     		if(fabs(start.x-end.x)>fabs(start.z-end.z)){
    -			float step=unitdef->xsize*8+buildSpacing*16;
    +			float step=tmp_xsize1*8+buildSpacing*16;
     			float3 dir=end-start;
     			if(dir.x==0){
     				ret.push_back(start);
    @@ -1478,7 +1524,7 @@
     			for(float3 p=start;fabs(p.x-start.x)<fabs(end.x-start.x)+step*0.4;p+=dir*step)
     				ret.push_back(p);
     		} else {
    -			float step=unitdef->ysize*8+buildSpacing*16;
    +			float step=tmp_ysize1*8+buildSpacing*16;
     			float3 dir=end-start;
     			if(dir.z==0){
     				ret.push_back(start);
    Index: C:/Springproject/rts/Game/UI/GuiHandler.h
    ===================================================================
    --- C:/Springproject/rts/Game/UI/GuiHandler.h	(revision 1559)
    +++ C:/Springproject/rts/Game/UI/GuiHandler.h	(working copy)
    @@ -47,6 +47,8 @@
     	CglList* list;
     	int buildSpacing;
     
    +	int buildFacing; // which side the built buildings should face?
    +
     	void CreateOptions(Command& c,bool rmb);
     	int GetDefaultCommand(int x,int y);
     	void DrawMapStuff(void);
    Index: C:/Springproject/rts/Map/BaseGroundDrawer.cpp
    ===================================================================
    --- C:/Springproject/rts/Map/BaseGroundDrawer.cpp	(revision 1559)
    +++ C:/Springproject/rts/Map/BaseGroundDrawer.cpp	(working copy)
    @@ -172,7 +172,7 @@
     							UnitDef *unitdef = unitDefHandler->GetUnitByID(-guihandler->commands[guihandler->inCommand].id);
     
     							CFeature* f;
    -							if(uh->TestUnitBuildSquare(float3(x*16+8,0,y*16+8),unitdef,f))
    +							if(uh->TestUnitBuildSquare(float3(x*16+8,0,y*16+8),unitdef,f,guihandler->buildFacing))
     								m=1;
     							else 
     								m=0;
    Index: C:/Springproject/rts/Rendering/UnitModels/UnitDrawer.cpp
    ===================================================================
    --- C:/Springproject/rts/Rendering/UnitModels/UnitDrawer.cpp	(revision 1559)
    +++ C:/Springproject/rts/Rendering/UnitModels/UnitDrawer.cpp	(working copy)
    @@ -470,6 +470,7 @@
     			if(camera->InView((*gbi)->pos,(*gbi)->model->radius*2)){
     				glPushMatrix();
     				glTranslatef3((*gbi)->pos);
    +				glRotatef((*gbi)->facing*1024*16*(180.0/32768.0),0,1,0);
     				(*gbi)->model->DrawStatic();
     				glPopMatrix();
     			}
    @@ -1013,7 +1014,7 @@
     	if (unit->model->textureType == 0){
     		/* 3DO */
     		SetupForUnitDrawing();
    -		unit->Draw();
    +        unit->Draw();
     		CleanUpUnitDrawing();
     	} else {
     		/* S3O */
    @@ -1035,7 +1036,7 @@
      * Note: does all the GL state setting for that one unit, so you might want
      * something else for drawing many translucent units.
      */
    -void CUnitDrawer::DrawBuildingSample(UnitDef* unitdef, int side, float3 pos)
    +void CUnitDrawer::DrawBuildingSample(UnitDef* unitdef, int side, float3 pos, int facing)
     {
     	S3DOModel* model=modelParser->Load3DO(unitdef->model.modelpath.c_str(), 1, side);
     
    @@ -1044,6 +1045,7 @@
     		SetupForGhostDrawing();
     		glPushMatrix();
     		glTranslatef3(pos);
    +		glRotatef((facing*1024*16)*(180.0/32768.0),0,1,0);
     		model->DrawStatic();
     		CleanUpGhostDrawing();
     		glPopMatrix();
    @@ -1082,6 +1084,7 @@
     	/* Push out the polygons. */
     	glPushMatrix();
     	glTranslatef3(pos);
    +	
     	model->DrawStatic();
     	glPopMatrix();
     
    Index: C:/Springproject/rts/Rendering/UnitModels/UnitDrawer.h
    ===================================================================
    --- C:/Springproject/rts/Rendering/UnitModels/UnitDrawer.h	(revision 1559)
    +++ C:/Springproject/rts/Rendering/UnitModels/UnitDrawer.h	(working copy)
    @@ -73,6 +73,7 @@
     		BuildingGroundDecal* decal;
     		float3 pos;
     		S3DOModel* model;
    +		int facing;
     	};
     	std::list<GhostBuilding*> ghostBuildings;	//these are buildings that where in LOS_PREVLOS when they died and havent been in los since then
     
    @@ -93,7 +94,7 @@
     	std::set<int> usedS3OTextures;
     
     	void SetS3OTeamColour(int team);
    -	void DrawBuildingSample(UnitDef* unitdef, int side, float3 pos);
    +	void DrawBuildingSample(UnitDef* unitdef, int side, float3 pos, int facing=0);
     
     	/* CUnit::Draw */
     	void UnitDrawingTexturesOff(S3DOModel *model);
    Index: C:/Springproject/rts/Sim/Objects/SolidObject.cpp
    ===================================================================
    --- C:/Springproject/rts/Sim/Objects/SolidObject.cpp	(revision 1559)
    +++ C:/Springproject/rts/Sim/Objects/SolidObject.cpp	(working copy)
    @@ -151,7 +151,7 @@
     void CSolidObject::Block() {
     	if(isMarkedOnBlockingMap)
     		UnBlock();
    -
    +	
     	if(blocking && (physicalState == OnGround || physicalState == Floating || physicalState == Hovering || physicalState == Submarine)){
     		//Using yardmap if available.
     		if(yardMap) {
    Index: C:/Springproject/rts/Sim/Objects/SolidObject.h
    ===================================================================
    --- C:/Springproject/rts/Sim/Objects/SolidObject.h	(revision 1559)
    +++ C:/Springproject/rts/Sim/Objects/SolidObject.h	(working copy)
    @@ -46,7 +46,7 @@
     	int ysize;									//The z-size of this object, according to it's footprint. NOTE: This one should have been called zsize!
     	float height;								//The height of this object.
     	short heading;								//Contains the same information as frontdir, but in a short signed integer.
    -
    +	
     	//Positional properties.
     	PhysicalState physicalState;				//The current state of the object within the gameworld. I.e Flying or OnGround.
     	float3 midPos;								//This is the calculated center position of the model (pos is usually at the very bottom of the model). Used as mass center.
    @@ -65,6 +65,7 @@
     	//Map
     	int2 mapPos;								//Current position on GroundBlockingMap.
     	unsigned char* yardMap;						//Current active yardmap of this object. 0 means no active yardmap => all blocked.
    +	int buildFacing;
     	bool isMarkedOnBlockingMap;					//Tells if this object are marked on the GroundBlockingMap.
     
     	//Old stuff. Used for back-compability. NOTE: Don't use whose!
    Index: C:/Springproject/rts/Sim/Units/CommandAI/BuilderCAI.cpp
    ===================================================================
    --- C:/Springproject/rts/Sim/Units/CommandAI/BuilderCAI.cpp	(revision 1559)
    +++ C:/Springproject/rts/Sim/Units/CommandAI/BuilderCAI.cpp	(working copy)
    @@ -135,6 +135,9 @@
     				buildPos.x=c.params[0];
     				buildPos.y=c.params[1];
     				buildPos.z=c.params[2];
    +				if(c.params[3])
    +				buildFacing=c.params[3];
    +				else buildFacing=0;
     				if(buildPos.distance2D(fac->pos)<fac->buildDistance*0.6+radius){
     					StopMove();
     					if(uh->maxUnits>(int)gs->Team(owner->team)->units.size()){
    @@ -140,7 +143,7 @@
     					if(uh->maxUnits>(int)gs->Team(owner->team)->units.size()){
     						buildRetries++;
     						owner->moveType->KeepPointingTo(buildPos, fac->buildDistance*0.7+radius, false);
    -						if(fac->StartBuild(boi->second,buildPos) || buildRetries>20){
    +						if(fac->StartBuild(boi->second,buildPos,buildFacing) || buildRetries>20){
     							building=true;
     						} else {
     							ENTER_MIXED;
    @@ -169,7 +172,11 @@
     			pos.z=floor(c.params[2]/SQUARE_SIZE+0.5)*SQUARE_SIZE;
     			pos.y=c.params[1];
     			CFeature* f=0;
    -			uh->TestUnitBuildSquare(pos,boi->second,f);
    +			if(c.params[3])
    +				buildFacing=c.params[3];
    +			else
    +				buildFacing=0;
    +			uh->TestUnitBuildSquare(pos,boi->second,f,buildFacing);
     			if(f){
     				Command c2;
     				c2.id=CMD_RECLAIM;
    @@ -673,6 +680,8 @@
     		map<int,string>::iterator boi;
     		if((boi=buildOptions.find(ci->id))!=buildOptions.end()){
     			pos=float3(ci->params[0],ci->params[1],ci->params[2]);
    +			int facing=0;
    +			if(ci->params[3])	facing=ci->params[3];
     			UnitDef *unitdef = unitDefHandler->GetUnitByName(boi->second);
     
     			glColor4f(1,1,1,0.4);
    @@ -695,7 +704,7 @@
     			}
     
     			glColor4f(1,1,1,0.3);
    -			unitDrawer->DrawBuildingSample(unitdef, owner->team, pos);
    +			unitDrawer->DrawBuildingSample(unitdef, owner->team, pos, facing);
     
     			glColor4f(1,1,1,0.4);
     			glBegin(GL_LINE_STRIP);
    @@ -727,10 +736,12 @@
     		if(c.params.size()<3)
     			return;
     		float3 pos(c.params[0],c.params[1],c.params[2]);
    +		if(c.params[3])		buildFacing=c.params[3];
    +		else	buildFacing=0;
     		UnitDef *unitdef = unitDefHandler->GetUnitByName(boi->second);
     		pos=helper->Pos2BuildPos(pos,unitdef);
     		CFeature* feature;
    -		if(!uh->TestUnitBuildSquare(pos,unitdef,feature)){
    +		if(!uh->TestUnitBuildSquare(pos,unitdef,feature,buildFacing)){
     			return;
     		}
     	}
    @@ -745,12 +756,40 @@
     		map<int,string>::iterator boi;
     		if((boi=buildOptions.find(ci->id))!=buildOptions.end()){
     			float3 pos=float3(ci->params[0],ci->params[1]+3,ci->params[2]);
    +			int facing=0;
    +			if(ci->params[3])	facing=ci->params[3];
     			UnitDef *unitdef = unitDefHandler->GetUnitByName(boi->second);
    +			
    +			int tmp_xsize=1;
    +			int tmp_ysize=1;
     
     			pos=helper->Pos2BuildPos(pos,unitdef);
    +			
    +			switch (facing)
    +			{
    +			case 0:
    +				tmp_xsize=unitdef->rxsize;
    +                tmp_ysize=unitdef->rysize;
    +				break;
    +			case 1:
    +				tmp_xsize=unitdef->rysize;
    +                tmp_ysize=unitdef->rxsize;
    +				break;
    +			case 2:
    +				tmp_xsize=unitdef->rxsize;
    +                tmp_ysize=unitdef->rysize;
    +				break;
    +			case 3:
    +				tmp_xsize=unitdef->rysize;
    +                tmp_ysize=unitdef->rxsize;
    +				break;
    +			default:
    +				tmp_xsize=unitdef->rxsize;
    +                tmp_ysize=unitdef->rysize;
    +			}
     
    -			float xsize=unitdef->xsize*4;
    -			float ysize=unitdef->ysize*4;
    +			float xsize=tmp_xsize*4;
    +			float ysize=tmp_ysize*4;
     			glColor4f(0.2,1,0.2,1);
     			glBegin(GL_LINE_STRIP);
     			glVertexf3(pos+float3(xsize,1,ysize));
    Index: C:/Springproject/rts/Sim/Units/CommandAI/BuilderCAI.h
    ===================================================================
    --- C:/Springproject/rts/Sim/Units/CommandAI/BuilderCAI.h	(revision 1559)
    +++ C:/Springproject/rts/Sim/Units/CommandAI/BuilderCAI.h	(working copy)
    @@ -27,6 +27,7 @@
     	map<int,string> buildOptions;
     	bool building;
     	float3 buildPos;
    +	int buildFacing;
     
     	float cachedRadius;
     	int cachedRadiusId;
    Index: C:/Springproject/rts/Sim/Units/CommandAI/CommandAI.cpp
    ===================================================================
    --- C:/Springproject/rts/Sim/Units/CommandAI/CommandAI.cpp	(revision 1559)
    +++ C:/Springproject/rts/Sim/Units/CommandAI/CommandAI.cpp	(working copy)
    @@ -425,14 +425,57 @@
     				} else if(c.params.size()>=3){		//we assume this means that the first 3 makes a position
     					float3 cpos(c.params[0],c.params[1],c.params[2]);
     					float3 cipos(ci->params[0],ci->params[1],ci->params[2]);
    +					int facing1=0;
    +					int facing2=0;
    +					int xsize1=1;
    +					int xsize2=1;
    +					int ysize1=1;
    +					int ysize2=1;
    +
    +					if (c.params[3])facing1=c.params[3];
    +					if (ci->params[3])facing2=ci->params[3];
     					if(c.id < 0){
     						UnitDef* u1 = unitDefHandler->GetUnitByID(-c.id);
     						UnitDef* u2 = unitDefHandler->GetUnitByID(-ci->id);
    +						switch(facing1){
    +							case 0:
    +								xsize1=u1->rxsize;
    +								ysize1=u1->rysize;
    +								break;
    +							case 1:
    +								xsize1=u1->rysize;
    +								ysize1=u1->rxsize;
    +								break;
    +							case 2:
    +								xsize1=u1->rxsize;
    +								ysize1=u1->rysize;
    +								break;
    +							case 3:
    +								xsize1=u1->rysize;
    +								ysize1=u1->rxsize;
    +								break;}
    +						switch(facing2){
    +							case 0:
    +								xsize2=u2->rxsize;
    +								ysize2=u2->rysize;
    +								break;
    +							case 1:
    +								xsize2=u2->rysize;
    +								ysize2=u2->rxsize;
    +								break;
    +							case 2:
    +								xsize2=u2->rxsize;
    +								ysize2=u2->rysize;
    +								break;
    +							case 3:
    +								xsize2=u2->rysize;
    +								ysize2=u2->rxsize;
    +								break;}
     						if(u1 && u2
    -							&& (fabs(cpos.x-cipos.x)*2 > max(u1->xsize, u2->xsize)*SQUARE_SIZE
    -							|| fabs(cpos.z-cipos.z)*2 > max(u1->ysize, u2->ysize)*SQUARE_SIZE)
    -							&& fabs(cpos.x-cipos.x)*2 < (u1->xsize + u2->xsize)*SQUARE_SIZE
    -							&& fabs(cpos.z-cipos.z)*2 < (u1->ysize + u2->ysize)*SQUARE_SIZE)
    +							&& (fabs(cpos.x-cipos.x)*2 > max(xsize1, xsize2)*SQUARE_SIZE
    +							|| fabs(cpos.z-cipos.z)*2 > max(ysize1, ysize2)*SQUARE_SIZE)
    +							&& fabs(cpos.x-cipos.x)*2 < (xsize1 + xsize2)*SQUARE_SIZE
    +							&& fabs(cpos.z-cipos.z)*2 < (ysize1 + ysize2)*SQUARE_SIZE)
     						{
     							v.push_back(*ci);
     						}
    Index: C:/Springproject/rts/Sim/Units/Unit.cpp
    ===================================================================
    --- C:/Springproject/rts/Sim/Units/Unit.cpp	(revision 1559)
    +++ C:/Springproject/rts/Sim/Units/Unit.cpp	(working copy)
    @@ -459,6 +459,7 @@
     		isCloaked=false;
     	}
     
    +
     	if(uh->waterDamage && (physicalState==CSolidObject::Floating || (physicalState==CSolidObject::OnGround && pos.y<=-3 && readmap->halfHeightmap[int((pos.z/(SQUARE_SIZE*2))*gs->hmapx+(pos.x/(SQUARE_SIZE*2)))]<-1))){
     		DoDamage(DamageArray()*uh->waterDamage,0,ZeroVector);
     	}
    @@ -618,7 +619,7 @@
     {
     	glPushMatrix();
     	float3 interPos=pos+speed*gu->timeOffset;
    -
    +	
     	if (physicalState == Flying && unitDef->canmove) {
     		//aircraft or skidding ground unit
     		CMatrix44f transMatrix(interPos,-rightdir,updir,frontdir);
    @@ -956,7 +957,6 @@
     void CUnit::Init(void)
     {
     	relMidPos=model->relMidPos;
    -
     	midPos=pos+frontdir*relMidPos.z + updir*relMidPos.y + rightdir*relMidPos.x;
     	losHeight=relMidPos.y+radius*0.5;
     	height = model->height;		//TODO: This one would be much better to have either in Constructor or UnitLoader!//why this is always called in unitloader
    Index: C:/Springproject/rts/Sim/Units/UnitDef.h
    ===================================================================
    --- C:/Springproject/rts/Sim/Units/UnitDef.h	(revision 1559)
    +++ C:/Springproject/rts/Sim/Units/UnitDef.h	(working copy)
    @@ -165,9 +165,17 @@
     	MoveData* movedata;
     //	unsigned char* yardmapLevels[6];
     	unsigned char* yardmap;				//Used for open ground blocking maps.
    -
    +	unsigned char* yardmap1;			//Iterations of the Ymap for building rotation
    +	unsigned char* yardmap2;
    +	unsigned char* yardmap3;
    +	unsigned char* yardmap4;
    +	
     	int xsize;									//each size is 8 units
     	int ysize;									//each size is 8 units
    +	int rxsize;			//real sizes of the unit for building rotation thing
    +	int rysize;
    +
    +	int buildangle;
     
     	float loadingRadius;	//for transports
     	int transportCapacity;
    Index: C:/Springproject/rts/Sim/Units/UnitDefHandler.cpp
    ===================================================================
    --- C:/Springproject/rts/Sim/Units/UnitDefHandler.cpp	(revision 1559)
    +++ C:/Springproject/rts/Sim/Units/UnitDefHandler.cpp	(working copy)
    @@ -73,6 +73,13 @@
     		unitDefs[i].filename = tafiles[a];
     		unitDefs[i].id = i;
     		unitDefs[i].yardmap = 0;
    +		unitDefs[i].yardmap1 = 0;
    +		unitDefs[i].yardmap2 = 0;
    +		unitDefs[i].yardmap3 = 0;
    +		unitDefs[i].yardmap4 = 0;
    +		unitDefs[i].rxsize = 1;
    +		unitDefs[i].rysize = 1;
    +		unitDefs[i].buildangle=0;
     		unitDefs[i].name = unitname;
     		unitDefs[i].unitimage = 0;
     		unitID[unitname] = i;
    @@ -196,6 +203,8 @@
     	ud.idleAutoHeal=atof(tdfparser.SGetValueDef("10", "UNITINFO\\IdleAutoHeal").c_str())*(16.0/30.0);
     	ud.idleTime=atoi(tdfparser.SGetValueDef("600", "UNITINFO\\IdleTime").c_str());
     
    +    ud.buildangle=atoi(tdfparser.SGetValueDef("0", "UNITINFO\\buildangle").c_str());
    +
     	ud.isMetalMaker=(ud.makesMetal>=1 && ud.energyUpkeep>ud.makesMetal*40);
     
     	ud.controlRadius=32;
    @@ -468,6 +477,9 @@
     	ud.xsize=atoi(tdfparser.SGetValueDef("1", "UNITINFO\\FootprintX").c_str())*2;//ta has only half our res so multiply size with 2
     	ud.ysize=atoi(tdfparser.SGetValueDef("1", "UNITINFO\\FootprintZ").c_str())*2;
     
    +	ud.rxsize=ud.xsize;
    +	ud.rysize=ud.ysize;
    +
     	ud.needGeo=false;
     	if(ud.type=="Building" || ud.type=="Factory"){
     		CreateYardMap(&ud, tdfparser.SGetValueDef("c", "UNITINFO\\YardMap"));
    @@ -589,6 +601,14 @@
     	//Creates the map.
     	def->yardmap = new unsigned char[def->xsize * def->ysize];
     	memset(def->yardmap, 1, def->xsize * def->ysize);	//Q: Needed?
    +	def->yardmap1 = new unsigned char[def->xsize * def->ysize];
    +	memset(def->yardmap1, 1, def->xsize * def->ysize);	//Q: Needed?
    +	def->yardmap2 = new unsigned char[def->xsize * def->ysize];
    +	memset(def->yardmap2, 1, def->xsize * def->ysize);	//Q: Needed?
    +	def->yardmap3 = new unsigned char[def->xsize * def->ysize];
    +	memset(def->yardmap3, 1, def->xsize * def->ysize);	//Q: Needed?
    +	def->yardmap4 = new unsigned char[def->xsize * def->ysize];
    +	memset(def->yardmap4, 1, def->xsize * def->ysize);	//Q: Needed?
     
     	unsigned char *originalMap = new unsigned char[def->xsize * def->ysize / 4];		//TAS resolution is double of TA resolution.
     	memset(originalMap, 1, def->xsize * def->ysize / 4);
    @@ -613,9 +633,13 @@
     		}
     	}
     	for(int y = 0; y < def->ysize; y++)
    -		for(int x = 0; x < def->xsize; x++)
    +		for(int x = 0; x < def->xsize; x++){
     			def->yardmap[x + y*def->xsize] = originalMap[x/2 + y/2*def->xsize/2];
    -
    +			def->yardmap1[x + y*def->xsize] = originalMap[x/2 + y/2*def->xsize/2];
    +			def->yardmap4[def->ysize*(x+1)-(y+1)] = originalMap[x/2 + y/2*def->xsize/2];
    +			def->yardmap3[(def->ysize*def->xsize)-(x + y*def->xsize+1)] = originalMap[x/2 + y/2*def->xsize/2];
    +			def->yardmap2[(def->ysize*def->xsize)-(def->ysize*(x+1)-(y+1)+1)] = originalMap[x/2 + y/2*def->xsize/2];
    +		}
     	delete[] originalMap;
     }
     
    Index: C:/Springproject/rts/Sim/Units/UnitHandler.cpp
    ===================================================================
    --- C:/Springproject/rts/Sim/Units/UnitHandler.cpp	(revision 1559)
    +++ C:/Springproject/rts/Sim/Units/UnitHandler.cpp	(working copy)
    @@ -224,11 +224,14 @@
     	int numBorder=0;
     	float borderh=0;
     
    +	int xsize=1;
    +	int ysize=1;
    +
     	float maxDif=unitdef->maxHeightDif;
    -	int x1 = (int)max(0.f,(pos.x-(unitdef->xsize*0.5f*SQUARE_SIZE))/SQUARE_SIZE);
    -	int x2 = min(gs->mapx,x1+unitdef->xsize);
    -	int z1 = (int)max(0.f,(pos.z-(unitdef->ysize*0.5f*SQUARE_SIZE))/SQUARE_SIZE);
    -	int z2 = min(gs->mapy,z1+unitdef->ysize);
    +	int x1 = (int)max(0.f,(pos.x-(xsize*0.5f*SQUARE_SIZE))/SQUARE_SIZE);
    +	int x2 = min(gs->mapx,x1+xsize);
    +	int z1 = (int)max(0.f,(pos.z-(ysize*0.5f*SQUARE_SIZE))/SQUARE_SIZE);
    +	int z2 = min(gs->mapy,z1+ysize);
     
     	if (x1 > gs->mapx) x1 = gs->mapx;
     	if (x2 < 0) x2 = 0;
    @@ -259,20 +262,43 @@
     	return h;
     }
     
    -int CUnitHandler::TestUnitBuildSquare(const float3& pos, std::string unit,CFeature *&feature)
    +int CUnitHandler::TestUnitBuildSquare(const float3& pos, std::string unit,CFeature *&feature, int facing)
     {
     	UnitDef *unitdef = unitDefHandler->GetUnitByName(unit);
    -	return TestUnitBuildSquare(pos, unitdef,feature);
    +	return TestUnitBuildSquare(pos, unitdef,feature, facing);
     }
     
    -int CUnitHandler::TestUnitBuildSquare(const float3& pos, const UnitDef *unitdef,CFeature *&feature)
    +int CUnitHandler::TestUnitBuildSquare(const float3& pos, const UnitDef *unitdef, CFeature *&feature, int facing)
     {
     	feature=0;
    +	int xsize=1;
    +	int ysize=1;
    +	switch(facing){
    +		case 0:
    +			xsize=unitdef->rxsize;
    +			ysize=unitdef->rysize;
    +			break;
    +		case 1:
    +			xsize=unitdef->rysize;
    +			ysize=unitdef->rxsize;
    +			break;
    +		case 2:
    +			xsize=unitdef->rxsize;
    +			ysize=unitdef->rysize;
    +			break;
    +		case 3:
    +			ysize=unitdef->rxsize;
    +			xsize=unitdef->rysize;
    +			break;
    +		default:
    +			xsize=unitdef->rxsize;
    +			ysize=unitdef->rysize;
    +			break;}
     
    -	int x1 = (int) (pos.x-(unitdef->xsize*0.5f*SQUARE_SIZE));
    -	int x2 = x1+unitdef->xsize*SQUARE_SIZE;
    -	int z1 = (int) (pos.z-(unitdef->ysize*0.5f*SQUARE_SIZE));
    -	int z2 = z1+unitdef->ysize*SQUARE_SIZE;
    +	int x1 = (int) (pos.x-(xsize*0.5f*SQUARE_SIZE));
    +	int x2 = x1+xsize*SQUARE_SIZE;
    +	int z1 = (int) (pos.z-(ysize*0.5f*SQUARE_SIZE));
    +	int z2 = z1+ysize*SQUARE_SIZE;
     	float h=GetBuildHeight(pos,unitdef);
     
     	int canBuild=2;
    @@ -279,10 +305,10 @@
     
     	if(unitdef->needGeo){
     		canBuild=0;
    -		std::vector<CFeature*> features=qf->GetFeaturesExact(pos,max(unitdef->xsize,unitdef->ysize)*6);
    +		std::vector<CFeature*> features=qf->GetFeaturesExact(pos,max(xsize,ysize)*6);
     		
     		for(std::vector<CFeature*>::iterator fi=features.begin();fi!=features.end();++fi){
    -			if((*fi)->def->geoThermal && fabs((*fi)->pos.x-pos.x)<unitdef->xsize*4-4 && fabs((*fi)->pos.z-pos.z)<unitdef->ysize*4-4){
    +			if((*fi)->def->geoThermal && fabs((*fi)->pos.x-pos.x)<xsize*4-4 && fabs((*fi)->pos.z-pos.z)<ysize*4-4){
     				canBuild=2;
     				break;
     			}
    @@ -345,12 +371,12 @@
     	return ret;
     }
     
    -int CUnitHandler::ShowUnitBuildSquare(const float3& pos, const UnitDef *unitdef)
    +int CUnitHandler::ShowUnitBuildSquare(const float3& pos, const UnitDef *unitdef, int facing)
     {
    -	return ShowUnitBuildSquare(pos, unitdef, std::vector<Command>());
    +	return ShowUnitBuildSquare(pos, unitdef, std::vector<Command>(),facing);
     }
     
    -int CUnitHandler::ShowUnitBuildSquare(const float3& pos, const UnitDef *unitdef, const std::vector<Command> &cv)
    +int CUnitHandler::ShowUnitBuildSquare(const float3& pos, const UnitDef *unitdef, const std::vector<Command> &cv, int facing)
     {
     	glDisable(GL_DEPTH_TEST );
     	glEnable(GL_BLEND);
    @@ -358,11 +384,35 @@
     	glDisable(GL_TEXTURE_2D);
     	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
     	glBegin(GL_QUADS);
    +	int xsize=1;
    +	int ysize=1;
     
    -	int x1 = (int) (pos.x-(unitdef->xsize*0.5f*SQUARE_SIZE));
    -	int x2 = x1+unitdef->xsize*SQUARE_SIZE;
    -	int z1 = (int) (pos.z-(unitdef->ysize*0.5f*SQUARE_SIZE));
    -	int z2 = z1+unitdef->ysize*SQUARE_SIZE;
    +		switch(facing){
    +		case 0:
    +			xsize=unitdef->rxsize;
    +			ysize=unitdef->rysize;
    +			break;
    +		case 1:
    +			xsize=unitdef->rysize;
    +			ysize=unitdef->rxsize;
    +			break;
    +		case 2:
    +			xsize=unitdef->rxsize;
    +			ysize=unitdef->rysize;
    +			break;
    +		case 3:
    +			ysize=unitdef->rxsize;
    +			xsize=unitdef->rysize;
    +			break;
    +		default:
    +			xsize=unitdef->rxsize;
    +			ysize=unitdef->rysize;
    +			break;}
    +
    +	int x1 = (int) (pos.x-(xsize*0.5f*SQUARE_SIZE));
    +	int x2 = x1+xsize*SQUARE_SIZE;
    +	int z1 = (int) (pos.z-(ysize*0.5f*SQUARE_SIZE));
    +	int z2 = z1+ysize*SQUARE_SIZE;
     	float h=GetBuildHeight(pos,unitdef);
     
     	int canbuild=2;
    @@ -369,10 +419,10 @@
     
     	if(unitdef->needGeo){
     		canbuild=0;
    -		std::vector<CFeature*> features=qf->GetFeaturesExact(pos,max(unitdef->xsize,unitdef->ysize)*6);
    +		std::vector<CFeature*> features=qf->GetFeaturesExact(pos,max(xsize,ysize)*6);
     
     		for(std::vector<CFeature*>::iterator fi=features.begin();fi!=features.end();++fi){
    -			if((*fi)->def->geoThermal && fabs((*fi)->pos.x-pos.x)<unitdef->xsize*4-4 && fabs((*fi)->pos.z-pos.z)<unitdef->ysize*4-4){
    +			if((*fi)->def->geoThermal && fabs((*fi)->pos.x-pos.x)<xsize*4-4 && fabs((*fi)->pos.z-pos.z)<ysize*4-4){
     				canbuild=2;
     				break;
     			}
    Index: C:/Springproject/rts/Sim/Units/UnitHandler.h
    ===================================================================
    --- C:/Springproject/rts/Sim/Units/UnitHandler.h	(revision 1559)
    +++ C:/Springproject/rts/Sim/Units/UnitHandler.h	(working copy)
    @@ -49,10 +49,10 @@
     	//0 blocked
     	//1 mobile unit in the way
     	//2 free (or if feature is != 0 then with a blocking feature that can be reclaimed)
    -	int  TestUnitBuildSquare(const float3& pos, const UnitDef *unitdef,CFeature *&feature);	//test if a unit can be built at specified position
    -	int  TestUnitBuildSquare(const float3& pos, std::string unit,CFeature *&feature);	//test if a unit can be built at specified position
    -	int  ShowUnitBuildSquare(const float3& pos, const UnitDef *unitdef);	//test if a unit can be built at specified position and show on the ground where it's to rough
    -	int  ShowUnitBuildSquare(const float3& pos, const UnitDef *unitdef, const std::vector<Command> &cv);
    +	int  TestUnitBuildSquare(const float3& pos, const UnitDef *unitdef,CFeature *&feature, int facing=0);	//test if a unit can be built at specified position
    +	int  TestUnitBuildSquare(const float3& pos, std::string unit,CFeature *&feature, int facing=0);	//test if a unit can be built at specified position
    +	int  ShowUnitBuildSquare(const float3& pos, const UnitDef *unitdef, int facing=0);	//test if a unit can be built at specified position and show on the ground where it's to rough
    +	int  ShowUnitBuildSquare(const float3& pos, const UnitDef *unitdef, const std::vector<Command> &cv, int facing=0);
     	int  TestBuildSquare(const float3& pos, const UnitDef *unitdef,CFeature *&feature);	//test a singel mapsquare for build possibility
     
     	void AddBuilderCAI(CBuilderCAI*);
    Index: C:/Springproject/rts/Sim/Units/UnitLoader.cpp
    ===================================================================
    --- C:/Springproject/rts/Sim/Units/UnitLoader.cpp	(revision 1559)
    +++ C:/Springproject/rts/Sim/Units/UnitLoader.cpp	(working copy)
    @@ -62,7 +62,7 @@
     {
     }
     
    -CUnit* CUnitLoader::LoadUnit(const string& name, float3 pos, int side, bool build)
    +CUnit* CUnitLoader::LoadUnit(const string& name, float3 pos, int side, bool build, int facing)
     {
     	CUnit* unit;
     START_TIME_PROFILE;
    @@ -112,6 +112,9 @@
     	unit->UnitInit (ud, side, pos);
     
     	unit->beingBuilt=build;
    +
    +
    +	unit->buildFacing=facing;
     	unit->power=ud->power;
     	unit->maxHealth=ud->health;
     	unit->health=ud->health;
    @@ -129,8 +132,6 @@
     	unit->realLosRadius=(int) (ud->losRadius/(SQUARE_SIZE*2));
     	unit->realAirLosRadius=(int) (ud->airLosRadius/(SQUARE_SIZE*4));
     	unit->upright=ud->upright;
    -	unit->xsize=ud->xsize;
    -	unit->ysize=ud->ysize;
     	unit->radarRadius=ud->radarRadius/(SQUARE_SIZE*8);
     	unit->sonarRadius=ud->sonarRadius/(SQUARE_SIZE*8);
     	unit->jammerRadius=ud->jammerRadius/(SQUARE_SIZE*8);
    @@ -297,8 +298,49 @@
     	unit->cob->Call(COBFN_Create);
     	unit->cob->Call("SetMaxReloadTime", relMax);
     
    +		switch(facing){
    +		case 0:
    + 			unit->xsize=ud->rxsize;
    +			unit->ysize=ud->rysize;
    +			break;
    +		case 1:
    + 			unit->xsize=ud->rysize;
    +			unit->ysize=ud->rxsize;
    +			break;
    +		case 2:
    + 			unit->xsize=ud->rxsize;
    +			unit->ysize=ud->rysize;
    +			break;
    +		case 3:
    + 			unit->xsize=ud->rysize;
    +			unit->ysize=ud->rxsize;
    +			break;
    +		default:
    + 			unit->xsize=ud->rxsize;
    +			unit->ysize=ud->rysize;
    +	}
    +
     	unit->Init();
     
    +	switch(facing){			// a little hack to bypass the CUnit Block() without a yardmap, so that the unit gets a closed yardmap when built.
    +		case 0:
    +            unit->yardMap=ud->yardmap1;
    +			break;
    +		case 1:
    +            unit->yardMap=ud->yardmap2;
    +			break;
    +		case 2:
    +            unit->yardMap=ud->yardmap3;
    +			break;
    +		case 3:
    +            unit->yardMap=ud->yardmap4;
    +			break;
    +		default:
    +            unit->yardMap=ud->yardmap1;
    +	}
    +
    +	if(facing)
    +	unit->heading=facing*16*1024;
     	if(!build)
     		unit->FinishedBuilding();
     
    Index: C:/Springproject/rts/Sim/Units/UnitLoader.h
    ===================================================================
    --- C:/Springproject/rts/Sim/Units/UnitLoader.h	(revision 1559)
    +++ C:/Springproject/rts/Sim/Units/UnitLoader.h	(working copy)
    @@ -16,7 +16,7 @@
     class CUnitLoader  
     {
     public:
    -	CUnit* LoadUnit(const string& name,float3 pos, int side, bool build=true);
    +	CUnit* LoadUnit(const string& name,float3 pos, int side, bool build=true, int facing=0);
     	CUnitLoader();
     	virtual ~CUnitLoader();
     
    Index: C:/Springproject/rts/Sim/Units/UnitTypes/Builder.cpp
    ===================================================================
    --- C:/Springproject/rts/Sim/Units/UnitTypes/Builder.cpp	(revision 1559)
    +++ C:/Springproject/rts/Sim/Units/UnitTypes/Builder.cpp	(working copy)
    @@ -200,7 +200,7 @@
     			}
     			if(curResurrect->resurrectProgress>1){		//resurrect finished
     				curResurrect->UnBlock();
    -				CUnit* u=unitLoader.LoadUnit(curResurrect->createdFromUnit,curResurrect->pos,team,false);
    +				CUnit* u=unitLoader.LoadUnit(curResurrect->createdFromUnit,curResurrect->pos,team,false,curResurrect->buildFacing);
     				u->health*=0.05;
     				lastResurrected=u->id;
     				curResurrect->resurrectProgress=0;
    @@ -345,7 +345,7 @@
     //	info->AddLine("stop build");
     }
     
    -bool CBuilder::StartBuild(const string &type, float3 &buildPos)
    +bool CBuilder::StartBuild(const string &type, float3 &buildPos, int facing)
     {
     	StopBuild(false);
     //	info->AddLine("start build");
    @@ -354,7 +354,7 @@
     	buildPos=helper->Pos2BuildPos(buildPos,unitdef);
     
     	CFeature* feature;
    -	int canBuild=uh->TestUnitBuildSquare(buildPos,unitdef,feature);
    +	int canBuild=uh->TestUnitBuildSquare(buildPos,unitdef,feature, facing);
     	if(canBuild<2){
     		CUnit* u=helper->GetClosestFriendlyUnit(buildPos,5,allyteam);
     		if(u && u->unitDef==unitdef){
    @@ -373,7 +373,7 @@
     		terraformLeft=0;
     	}
     	else {
    -		CalculateBuildTerraformCost(buildPos, unitdef);
    +		CalculateBuildTerraformCost(buildPos, unitdef, facing);
     
     		terraforming=true;
     		terraformType=Terraform_Building;
    @@ -386,7 +386,7 @@
     	nextBuildType=type;
     	nextBuildPos=buildPos;
     
    -	CUnit* b=unitLoader.LoadUnit(nextBuildType,nextBuildPos,team,true);
    +	CUnit* b=unitLoader.LoadUnit(nextBuildType,nextBuildPos,team,true, facing);
     	AddDeathDependence(b);
     	curBuild=b;
     	if (mapDamage->disabled && !(curBuild->floatOnWater)) {
    @@ -413,8 +413,10 @@
     	return true;
     }
     
    -void CBuilder::CalculateBuildTerraformCost(float3 buildPos, UnitDef * unitdef)
    +void CBuilder::CalculateBuildTerraformCost(float3 buildPos, UnitDef * unitdef, int facing)
     {
    +	
    +
     	tx1 = (int)max((float)0,(buildPos.x-(unitdef->xsize*0.5f*SQUARE_SIZE))/SQUARE_SIZE);
     	tx2 = min(gs->mapx,tx1+unitdef->xsize);
     	tz1 = (int)max((float)0,(buildPos.z-(unitdef->ysize*0.5f*SQUARE_SIZE))/SQUARE_SIZE);
    Index: C:/Springproject/rts/Sim/Units/UnitTypes/Builder.h
    ===================================================================
    --- C:/Springproject/rts/Sim/Units/UnitTypes/Builder.h	(revision 1559)
    +++ C:/Springproject/rts/Sim/Units/UnitTypes/Builder.h	(working copy)
    @@ -23,8 +23,8 @@
     	void SlowUpdate(void);
     	void DependentDied(CObject* o);
     
    -	bool StartBuild(const string& type,float3& pos);
    -	void CalculateBuildTerraformCost(float3 buildPos, UnitDef * unitdef);
    +	bool StartBuild(const string& type,float3& pos, int facing);
    +	void CalculateBuildTerraformCost(float3 buildPos, UnitDef * unitdef, int facing);
     	void StopBuild(bool callScript=true);
     	void SetRepairTarget(CUnit* target);
     	void SetReclaimTarget(CSolidObject* object);
    Index: C:/Springproject/rts/Sim/Units/UnitTypes/Building.cpp
    ===================================================================
    --- C:/Springproject/rts/Sim/Units/UnitTypes/Building.cpp	(revision 1559)
    +++ C:/Springproject/rts/Sim/Units/UnitTypes/Building.cpp	(working copy)
    @@ -37,6 +37,7 @@
     			gb->pos=pos;
     			gb->model=model;
     			gb->decal=buildingDecal;
    +			gb->facing=buildFacing;
     			unitDrawer->ghostBuildings.push_back(gb);
     			mygb=gb;
     		}
    Index: C:/Springproject/rts/Sim/Units/UnitTypes/Factory.cpp
    ===================================================================
    --- C:/Springproject/rts/Sim/Units/UnitTypes/Factory.cpp	(revision 1559)
    +++ C:/Springproject/rts/Sim/Units/UnitTypes/Factory.cpp	(working copy)
    @@ -79,7 +79,7 @@
     		}
     		if(canBuild){
     			quedBuild=false;
    -			CUnit* b=unitLoader.LoadUnit(nextBuild,buildPos+float3(0.01,0.01,0.01),team,true);
    +			CUnit* b=unitLoader.LoadUnit(nextBuild,buildPos+float3(0.01,0.01,0.01),team,true,0);
     			AddDeathDependence(b);
     			curBuild=b;
     
    @@ -174,7 +174,7 @@
     
     	if(!opening){
     		cob->Call(COBFN_Activate);
    -		readmap->OpenBlockingYard(this, unitDef->yardmap);
    +		readmap->OpenBlockingYard(this, this->yardMap);
     		opening=true;
     	}
     }
    Index: C:/Springproject/rts/build/vstudio7/rts.vcproj
    ===================================================================
    --- C:/Springproject/rts/build/vstudio7/rts.vcproj	(revision 1559)
    +++ C:/Springproject/rts/build/vstudio7/rts.vcproj	(working copy)
    @@ -206,6 +206,9 @@
     			Name="External AI"
     			Filter="">
     			<File
    +				RelativePath="..\..\ExternalAI\aibase.h">
    +			</File>
    +			<File
     				RelativePath="..\..\ExternalAI\AICallback.cpp">
     			</File>
     			<File
    @@ -2246,6 +2249,12 @@
     					RelativePath="..\..\System\FileSystem\ArchiveBuffered.h">
     				</File>
     				<File
    +					RelativePath="..\..\System\FileSystem\ArchiveDir.cpp">
    +				</File>
    +				<File
    +					RelativePath="..\..\System\FileSystem\ArchiveDir.h">
    +				</File>
    +				<File
     					RelativePath="..\..\System\FileSystem\ArchiveFactory.cpp">
     				</File>
     				<File
    
    diff file icon Rotating Buildings.diff (44,086 bytes) 2006-07-01 22:47 +

-Relationships
+Relationships

-Notes

~0000281

tvo (reporter)

Ok, I finally found time to review it properly now my last exam is finally done.

First off, there's too much code duplications, as Jelmer said earlier. Mostly these switch statements. You should see a common thing in all of them: they read xsize,ysize from a unitdef and swap them around a bit based on one integer variable. So I suggest you add 2 functions to CUnitDef (you can leave comments out), look at dontLand in CUnitDef for an example.

int GetXsize(int facing) const {
  // If facing is even, xsize is returned.
  // If facing is odd, ysize is returned.
  return (facing & 1) == 0 ? xsize : ysize;
}
int GetYsize(int facing) const {
  // If facing is even, ysize is returned.
  // If facing is odd, xsize is returned.
  return (facing & 1) == 1 ? xsize : ysize;
}

Having done this you can replace all switch statements by code like (notice the massive code reduction this gives!):

int temp_xsize = ud->GetXsize(facing);
int temp_ysize = ud->GetYsize(facing);

For the yardmap I noticed you introduced a yardmapLevel as an array of yardmaps. Using that could save you from the switch statement for choosing the right yardmap. If you commented it out because you didn't get it working, you can do the yardmap the same as xsize and ysize above: make a function 'unsigned char* GetYardmap(int facing) const' and replace the switch statement by a call to that function.

Also, it seems you implemented it using rxsize and rysize, but I didn't find any assignments to those other then rxsize = xsize and rysize = ysize, suggesting rxsize and rysize are just redundant. If this is true, could you remove rxsize and rysize and substitute references to them with xsize and ysize.

Almost the same applies to the yardmap. I noticed that after applying the patch, there are 5 yardmaps, one for every direction and one extra for direction 0. I'd suggest you remove your yardmap1 and use yardmap instead, as they (yardmap and yardmap1) seem to have equal content. This way the API will be backwards compatible with AIs.

One last point: you still use
  if (c.params[3])
    facing = c.params[3];
This is invalid and may crash/desync/etc, because you reference element 3 in the if, when it is possibly not available. What you want here is:
  if (c.params.size() >= 4)
    facing = c.params[3];

I hope I'm not demotivating you by giving so much comments so late after you submitted it. I rather hope you learn from it, so your next patches will be right the first time :-)

cheers
Tobi

~0000284

Sean Mirrsen (reporter)

I didn't introduce YardmapLevels, some of the original devs did. I don't have the slightest idea of what it's for. rxsize and rysize are used as storage for Real sizes, as a reference to set the xsize and ysize when a non-square building is rotated. I left the original yardmap to avoid switching it around, and just setting it to one of the four other yardmaps as per the facing. As for the code reduction with those processes, I think a reference to a set variable is less cpu-intensive than calling a procedure, no matter how microscopic the difference might be. Sure it looks prettier in code form, but the compiled result seems better done my way. I'll have a go at doing it your way though, it might just work. ;)
I need assistance rotating building decals, working out a formula to rotate the vertexarray in creation is boiling my brain...
+Notes

-Issue History
Date Modified Username Field Change
2006-07-01 22:47 Sean Mirrsen New Issue
2006-07-01 22:47 Sean Mirrsen File Added: Rotating Buildings.diff
2006-07-06 17:14 tvo Note Added: 0000281
2006-07-06 18:51 Sean Mirrsen Note Added: 0000284
2006-08-05 00:17 jcnossen Status new => closed
2006-08-05 00:17 jcnossen Resolution open => fixed
+Issue History