Esempio n. 1
0
unsigned char TerrainData::GetEdgeType(LandscapeType landsCape, TerrainType t1, TerrainType t2)
{
    static boost::array< boost::array< boost::array<unsigned char, TT_COUNT>, TT_COUNT >, LT_COUNT > EDGE_TABLE;
    static bool isInitialized = false;
    if(!isInitialized)
    {
        // Init table for faster access
        for(int lt = 0; lt < LT_COUNT; ++lt)
            for(int iT1 = 0; iT1 < TT_COUNT; ++iT1)
                for(int iT2 = 0; iT2<=iT1; ++iT2)
                {
                    EdgeType et1 = GetEdgeType(LandscapeType(lt), TerrainType(iT1));
                    EdgeType et2 = GetEdgeType(LandscapeType(lt), TerrainType(iT2));
                    if(iT1 == iT2 || // Same terrain 
                        !TERRAIN_DRAW_PRIORITY[lt][iT1][iT2]) // Same priority
                    {
                        // -> No overdraw
                        EDGE_TABLE[lt][iT1][iT2] = 0;
                        EDGE_TABLE[lt][iT2][iT1] = 0;
                    }else if(TERRAIN_DRAW_PRIORITY[lt][iT1][iT2] > 0)
                    {
                        // T1 over T2
                        EDGE_TABLE[lt][iT1][iT2] = et1;
                        EDGE_TABLE[lt][iT2][iT1] = 0;
                    }else
                    {
                        // T2 over T1
                        EDGE_TABLE[lt][iT1][iT2] = 0;
                        EDGE_TABLE[lt][iT2][iT1] = et2;
                    }
                }
        isInitialized = true;
    }
    return EDGE_TABLE[landsCape][t1][t2];
}
void PreviewMinimap::SetMap(const glArchivItem_Map& s2map)
{
    map_width = s2map.getHeader().getWidth();
    map_height = s2map.getHeader().getHeight();

    unsigned char gfxSet = s2map.getHeader().getGfxSet();
    RTTR_Assert(gfxSet < LT_COUNT);
    lt = LandscapeType(gfxSet);
    objects = s2map.GetLayer(MAP_TYPE);
    terrain1 = s2map.GetLayer(MAP_TERRAIN1);
    terrain2 = s2map.GetLayer(MAP_TERRAIN2);
    if(s2map.HasLayer(MAP_SHADOWS))
        shadows = s2map.GetLayer(MAP_SHADOWS);
    else
        CalcShadows(s2map.GetLayer(MAP_ALTITUDE));

    CreateMapTexture();
}
Esempio n. 3
0
void GameWorld::Scan(glArchivItem_Map *map)
{
	width = map->getHeader().getWidth();
	height = map->getHeader().getHeight();
	lt = LandscapeType(map->getHeader().getGfxSet());

	Init();

	// Dummy-Hafenpos für Index 0 einfügen // ask Oliverr why!
	// -> I just did, the dummy is so that the harbor "0" might be used for ships with no particular destination
	// poc: if you ever remove this dummy go to GameWorldBase::CalcDistanceToNearestHarbor and fix the loop to include the first harbor again (think Ive seen other instances of dummyadjusted loops as well...)
	GameWorldBase::HarborPos dummy = {0,0};
	harbor_pos.push_back(dummy);

	// Andere Sachen setzen
	for(unsigned y = 0;y<height;++y)
	{
		for(unsigned x = 0;x<width;++x)
		{
			MapNode& node = nodes[y*width+x];

			node.roads[2] = node.roads[1] = node.roads[0] = 0;
			node.roads_real[2] = node.roads_real[1] = node.roads_real[0] = false;
			node.altitude = map->GetMapDataAt(MAP_ALTITUDE, x, y);
			// Aufpassen, dass die Terrainindizes im Rahmen liegen, ansonsten 0 nehmen, unbekanntes Terrain (Bsp. 
			// Karte "Drachenebene")
			unsigned char t1 = map->GetMapDataAt(MAP_TERRAIN1, x, y), t2 = map->GetMapDataAt(MAP_TERRAIN2, x, y);
			
			// Hafenplatz?
			if(t1 >= 0x40 && t1 <= 0x54)
			{
				t1 -= 0x40;

				GameWorldBase::HarborPos p = {x,y};
				node.harbor_id = harbor_pos.size();
				harbor_pos.push_back(p);
			}
			else
				node.harbor_id = 0;
				
	

			node.t1 = (t1<20)?TERRAIN_INDIZES[t1]:0;
			node.t2 = (t2<20)?TERRAIN_INDIZES[t2]:0;

			node.resources = map->GetMapDataAt(MAP_RESOURCES, x, y);
			
			// Wasser?
			if(node.resources == 0x20 || node.resources == 0x21)
			{
				// TODO: Berge hatten komische Wasserbeeinflussung
				// ggf 0-4 Wasser setzen
				if( (node.t1 == TT_DESERT || node.t2 == TT_DESERT) ||
					(node.t1 == TT_WATER || node.t2 == TT_WATER) )
					node.resources = 0; // Kein Wasser, in der Wüste, da isses trocken!
				else if( (node.t1 == TT_STEPPE || node.t2 == TT_STEPPE) )
					node.resources = 0x23; // 2 Wasser
				else if( (node.t1 == TT_SAVANNAH || node.t2 == TT_SAVANNAH) )
					node.resources = 0x25; // 4 Wasser
				else
					node.resources = 0x27; // 7 Wasser
			}
			
			node.reserved = false;
			node.owner = 0;
			for(unsigned i = 0;i<4;++i)
				node.boundary_stones[i] = 0;
			node.sea_id = 0;
			
			// FOW-Zeug initialisieren
			for(unsigned i = 0;i<GameClient::inst().GetPlayerCount();++i)
			{
				switch(GameClient::inst().GetGGS().exploration)
				{
				case GlobalGameSettings::EXP_DISABLED:
					{
						node.fow[i].visibility = VIS_VISIBLE;
					} break;
				case GlobalGameSettings::EXP_CLASSIC:
					{
						node.fow[i].visibility = VIS_INVISIBLE;
					} break;
				case GlobalGameSettings::EXP_FOGOFWAR:
					{
						node.fow[i].visibility = VIS_INVISIBLE;
					} break;
				case GlobalGameSettings::EXP_FOGOFWARE_EXPLORED:
					{
						node.fow[i].visibility = VIS_FOW;
					} break;
				}
		
				node.fow[i].last_update_time = 0;
				node.fow[i].object = NULL;
				node.fow[i].roads[0] = node.fow[i].roads[1] =
					node.fow[i].roads[2] = 0;
				node.fow[i].owner = 0;
				for(unsigned z = 0;z<4;++z)
					node.fow[i].boundary_stones[z] = 0;
			}
		}
	}

	std::vector< Point<MapCoord> > headquarter_positions;

	// Objekte auslesen
	for(unsigned y = 0;y<height;++y)
	{
		for(unsigned x = 0;x<width;++x)
		{
			unsigned int pos = y*width+x;
			unsigned char lc = map->GetMapDataAt(MAP_LANDSCAPE, x, y);

			switch(map->GetMapDataAt(MAP_TYPE, x, y))
			{
			// Player Startpos (provisorisch)
			case 0x80:
				{
					headquarter_positions.push_back(Point<MapCoord>(x, y));

					if(lc < GAMECLIENT.GetPlayerCount())
					{
						GetPlayer(lc)->hqx = x;
						GetPlayer(lc)->hqy = y;
						nodes[pos].obj = NULL;
					}
				} break;

			// Baum 1-4
			case 0xC4:
				{
					if(lc >= 0x30 && lc <= 0x3D)
						nodes[pos].obj = new noTree(x,y,0,3);
					else if(lc >= 0x70 && lc <= 0x7D)
						nodes[pos].obj = new noTree(x,y,1,3);
					else if(lc >= 0xB0 && lc <= 0xBD)
						nodes[pos].obj = new noTree(x,y,2,3);
					else if(lc >= 0xF0 && lc <= 0xFD)
						nodes[pos].obj = new noTree(x,y,3,3);
					else
					{
						LOG.lprintf("Unbekannter Baum1-4 auf x=%d, y=%d: id=%d (0x%0X)\n", x, y, lc, lc);
						nodes[pos].obj = NULL;
					}
				} break;

			// Baum 5-8
			case 0xC5:
					{
					if(lc >= 0x30 && lc <= 0x3D)
						nodes[pos].obj = new noTree(x,y,4,3);
					else if(lc >= 0x70 && lc <= 0x7D)
						nodes[pos].obj = new noTree(x,y,5,3);
					else if(lc >= 0xB0 && lc <= 0xBD)
						nodes[pos].obj = new noTree(x,y,6,3);
					else if(lc >= 0xF0 && lc <= 0xFD)
						nodes[pos].obj = new noTree(x,y,7,3);
					else
					{
						LOG.lprintf("Unbekannter Baum5-8 auf x=%d, y=%d: id=%d (0x%0X)\n", x, y, lc, lc);
						nodes[pos].obj = NULL;
					}
				} break;

			// Baum 9
			case 0xC6:
				{
					if(lc >= 0x30 && lc <= 0x3D)
						nodes[pos].obj = new noTree(x,y,8,3);
					else
					{
						LOG.lprintf("Unbekannter Baum9 auf x=%d, y=%d: id=%d (0x%0X)\n", x, y, lc, lc);
						nodes[pos].obj = NULL;
					}
				} break;

			// Sonstiges Naturzeug ohne Funktion, nur zur Dekoration
			case 0xC8:
				{
					/// @todo mis0bobs unvollständig (dieses lagerzelt), 4 und 5 überhaupt nicht erwähnt
					// mis1bobs, 2 und 3 sind vollständig eingebaut

					// Objekte aus der map_?_z.lst
					if(lc <= 0x0A)
						nodes[pos].obj = new noEnvObject(x, y, 500+lc);

					// "wasserstein" aus der map_?_z.lst
					else if(lc == 0x0B)
						nodes[pos].obj = new noStaticObject(x, y, 500+lc);

					// Objekte aus der map_?_z.lst
					else if(lc >= 0x0C && lc <= 0x0F)
						nodes[pos].obj = new noEnvObject(x, y, 500+lc);

					// Objekte aus der map.lst
					else if(lc >= 0x10 && lc <= 0x14)
						nodes[pos].obj = new noEnvObject(x, y, 542+lc-0x10);

					// gestrandetes Schiff (mis0bobs, unvollständig)
					else if(lc == 0x15)
						nodes[pos].obj = new noStaticObject(x, y, (lc-0x15)*2, 0, 1);

					// das Tor aus der map_?_z.lst
					else if(lc == 0x16)
						nodes[pos].obj = new noStaticObject(x, y, 560, 0xFFFF, 2);

					// das geöffnete Tor aus map_?_z.lst
					else if(lc == 0x17)
						nodes[pos].obj = new noStaticObject(x, y, 561, 0xFFFF, 2);

					// Stalagmiten (mis1bobs)
					else if(lc >= 0x18 && lc <= 0x1E)
						nodes[pos].obj = new noStaticObject(x, y, (lc-0x18)*2, 1);

					// toter Baum (mis1bobs)
					else if(lc >= 0x1F && lc <= 0x20)
						nodes[pos].obj = new noStaticObject(x, y, 20+(lc-0x1F)*2, 1);

					// Gerippe (mis1bobs)
					else if(lc == 0x21)
						nodes[pos].obj = new noEnvObject(x, y, 30, 1);

					// Objekte aus der map.lst
					else if(lc >= 0x22 && lc <= 0x27)
						nodes[pos].obj = new noEnvObject(x, y, 550+lc-0x22);

					// Objekte aus der map.lst
					else if(lc >= 0x28 && lc <= 0x2B)
						nodes[pos].obj = new noEnvObject(x, y, 556+lc-0x28);

					// die "kaputten" Gebäuderuinen usw (mis2bobs)
					else if(lc >= 0x2C && lc <= 0x2D)
						nodes[pos].obj = new noStaticObject(x, y, (lc-0x2C)*2, 2);
					else if(lc == 0x2E)
						nodes[pos].obj = new noStaticObject(x, y, (lc-0x2C)*2, 2, 1);
					else if(lc == 0x2F)
						nodes[pos].obj = new noStaticObject(x, y, (lc-0x2C)*2, 2, 2);
					else if(lc == 0x30)
						nodes[pos].obj = new noEnvObject(x, y, (lc-0x2C)*2, 2);

					// der Wikinger (mis3bobs)
					else if(lc == 0x31)
						nodes[pos].obj = new noStaticObject(x, y, 0, 2);

					else
					{
						LOG.lprintf("Unbekanntes Naturzeug auf x=%d, y=%d: id=%d (0x%0X)\n", x, y, lc, lc);
						nodes[pos].obj = NULL;
					}

				} break;

			// Granit Typ 1
			case 0xCC:
				{
					if(lc >= 0x01 && lc <= 0x06)
						nodes[pos].obj = new noGranite(GT_1,lc-1);
					else
					{
						LOG.lprintf("Unbekannter Granit1 auf x=%d, y=%d: id=%d (0x%0X)\n", x, y, lc, lc);
						nodes[pos].obj = NULL;
					}
				} break;

			// Granit Typ 2
			case 0xCD:
				{
					if(lc >= 0x01 && lc <= 0x06)
						nodes[pos].obj = new noGranite(GT_2,lc-1);
					else
					{
						LOG.lprintf("Unbekannter Granit2 auf x=%d, y=%d: id=%d (0x%0X)\n", x, y, lc, lc);
						nodes[pos].obj = NULL;
					}
				} break;

				// Nichts
			case 0:
				{
					nodes[pos].obj = NULL;
				} break;

			default:
				{
					/*LOG.lprintf("Unbekanntes Objekt %d (0x%0X) auf x=%d, y=%d: id=%d (0x%0X)\n", map->map_type[y*width+x], map->map_type[y*width+x], x, y, lc, lc);
		*/			nodes[pos].obj = NULL;
				} break;
			}
		}
	}

	// BQ mit nichts erstmal inititalisieren (HQ-Setzen berechnet diese neu und braucht sie)
	for(unsigned y = 0;y<height;++y)
	{
		for(unsigned x = 0;x<width;++x)
		{
			SetBQ(x,y,BQ_NOTHING);
		}
	}

	//random locations? -> randomize them :)
	if (GameClient::inst().GetGGS().random_location)
	{
		ptrdiff_t (*p_myrandom)(ptrdiff_t) = myRandom;
		std::random_shuffle(headquarter_positions.begin(), headquarter_positions.end(), p_myrandom);

		for (unsigned i = 0; i < GAMECLIENT.GetPlayerCount(); ++i)
		{
			GetPlayer(i)->hqx = headquarter_positions.at(i).x;
			GetPlayer(i)->hqy = headquarter_positions.at(i).y;
		}
	}

	// HQ setzen
	for(unsigned i = 0;i<GAMECLIENT.GetPlayerCount();++i)
	{
		// Existiert überhaupt ein HQ?
		if(GetPlayer(i)->hqx != 0xFFFF)
		{
			if(GetPlayer(i)->ps == PS_OCCUPIED || GetPlayer(i)->ps == PS_KI)
			{
				nobHQ * hq = new nobHQ(GetPlayer(i)->hqx,GetPlayer(i)->hqy,i,GetPlayer(i)->nation);
				SetNO(hq,GetPlayer(i)->hqx,GetPlayer(i)->hqy);
				GetPlayer(i)->AddWarehouse(reinterpret_cast<nobBaseWarehouse*>(hq));
			}
			/*else
				GetNode(GetPlayer(i)->hqx,GetPlayer(i)->hqy).obj = 0;*/
		}
	}

	// Tiere auslesen
	for(unsigned y = 0;y<height;++y)
	{
		for(unsigned x = 0;x<width;++x)
		{
			// Tiere setzen
			Species species;
			switch(map->GetMapDataAt(MAP_ANIMALS, x, y))
			{
			// TODO: Welche ID ist Polarbär?
			case 1: species = Species(SPEC_RABBITWHITE+RANDOM.Rand(__FILE__,__LINE__,0,2)); break; // zufällige Hasenart nehmen
			case 2: species = SPEC_FOX; break;
			case 3: species = SPEC_STAG; break;
			case 4: species = SPEC_DEER; break;
			case 5: species = SPEC_DUCK; break;
			case 6: species = SPEC_SHEEP; break;
			default: species = SPEC_NOTHING; break;
			}

			if(species != SPEC_NOTHING)
			{
				noAnimal * animal = new noAnimal(species,x,y);
				AddFigure(animal,x,y);
				// Loslaufen
				animal->StartLiving();
			}

			/// 4 Fische setzen
			if(map->GetMapDataAt(MAP_RESOURCES,y*width+x) > 0x80 && map->GetMapDataAt(MAP_RESOURCES,y*width+x)  < 0x90)
				GetNode(x,y).resources = 0x84;
		}
	}

	/// Weltmeere vermessen
	for(unsigned y = 0;y<height;++y)
	{
		for(unsigned x = 0;x<width;++x)
		{
			// Noch kein Meer an diesem Punkt?
			if(!GetNode(x,y).sea_id)
			{
				// Aber trotzdem Teil eines noch nicht vermessenen Meeres?
				if(IsSeaPoint(x,y))
				{
					unsigned sea_size = MeasureSea(x,y,seas.size());
					seas.push_back(Sea(sea_size));
				}
			}
		}
	}

	/// Die Meere herausfinden, an die die Hafenpunkte grenzen
	for(unsigned i = 0;i<harbor_pos.size();++i)
	{
		for(unsigned z = 0;z<6;++z)
			harbor_pos[i].cps[z].sea_id = IsCoastalPoint(GetXA(harbor_pos[i].x,harbor_pos[i].y,z),
			GetYA(harbor_pos[i].x,harbor_pos[i].y,z));
	}

	// Nachbarn der einzelnen Hafenplätze ermitteln
	CalcHarborPosNeighbors();

	/// Schatten und BQ berechnen
	for(unsigned y = 0;y<height;++y)
	{
		for(unsigned x = 0;x<width;++x)
		{
			RecalcShadow(x,y);
			SetBQ(x,y,GAMECLIENT.GetPlayerID());
		}
	}

	/// Bei FoW und aufgedeckt müssen auch die ersten FoW-Objekte erstellt werden
	if(GameClient::inst().GetGGS().exploration == GlobalGameSettings::EXP_FOGOFWARE_EXPLORED)
	{
		for(unsigned y = 0;y<height;++y)
		{
			for(unsigned x = 0;x<width;++x)
			{
				// Alle Spieler durchgehen
				for(unsigned i = 0;i<GameClient::inst().GetPlayerCount();++i)
				{
					// An der Stelle FOW für diesen Spieler?
					if(GetNode(x,y).fow[i].visibility == VIS_FOW)
						SaveFOWNode(x,y,i);
				}
			}
		}
	}
		
}
Esempio n. 4
0
void GameWorld::Deserialize(SerializedGameData *sgd)
{
	// Headinformationen
	width = sgd->PopUnsignedShort();
	height = sgd->PopUnsignedShort();
	lt = LandscapeType(sgd->PopUnsignedChar());

	// Initialisierungen
	Init();

	// Obj-ID-Counter setzen
	GameObject::SetObjIDCounter(sgd->PopUnsignedInt());

	// Trade graphs
	// Only if trade is enabled
	if(GameClient::inst().GetGGS().isEnabled(ADDON_TRADE))
	{
		tgs.resize(sgd->PopUnsignedChar());
		for(unsigned i = 0;i<tgs.size();++i)
			tgs[i] = new TradeGraph(sgd,this);
	}

	// Alle Weltpunkte serialisieren
	for(unsigned i = 0;i<map_size;++i)
	{
		for(unsigned z = 0;z<3;++z)
		{
			nodes[i].roads[z] = sgd->PopUnsignedChar();
			nodes[i].roads_real[z] = nodes[i].roads[z] ? true : false;
		}


		nodes[i].altitude = sgd->PopUnsignedChar();
		nodes[i].shadow = sgd->PopUnsignedChar();
		nodes[i].t1 = sgd->PopUnsignedChar();
		nodes[i].t2 = sgd->PopUnsignedChar();
		nodes[i].resources = sgd->PopUnsignedChar();
		nodes[i].reserved = sgd->PopBool();
		nodes[i].owner = sgd->PopUnsignedChar();
		for(unsigned b = 0;b<4;++b)
			nodes[i].boundary_stones[b] = sgd->PopUnsignedChar();
		nodes[i].bq = BuildingQuality(sgd->PopUnsignedChar());
		for(unsigned z = 0;z<GameClient::inst().GetPlayerCount();++z)
		{
			nodes[i].fow[z].visibility = Visibility(sgd->PopUnsignedChar());
			// Nur im FoW können FOW-Objekte stehen
			if(nodes[i].fow[z].visibility == VIS_FOW)
			{
				nodes[i].fow[z].last_update_time = sgd->PopUnsignedInt();
				nodes[i].fow[z].object = sgd->PopFOWObject();
				for(unsigned r = 0;r<3;++r)
					nodes[i].fow[z].roads[r] = sgd->PopUnsignedChar();
				nodes[i].fow[z].owner = sgd->PopUnsignedChar();
				for(unsigned b = 0;b<4;++b)
					nodes[i].fow[z].boundary_stones[b] = sgd->PopUnsignedChar();
			}
			else
			{
				nodes[i].fow[z].last_update_time = 0;
				nodes[i].fow[z].object = NULL;
				for(unsigned r = 0;r<3;++r)
					nodes[i].fow[z].roads[r] = 0;
				nodes[i].fow[z].owner = 0;
				for(unsigned b = 0;b<4;++b)
					nodes[i].fow[z].boundary_stones[b] = 0;
			}
		}
		nodes[i].obj = sgd->PopObject<noBase>(GOT_UNKNOWN);
		sgd->PopObjectList<noBase>(nodes[i].figures,GOT_UNKNOWN);
		nodes[i].sea_id = sgd->PopUnsignedShort();
		nodes[i].harbor_id = sgd->PopUnsignedInt();

		if(nodes[i].harbor_id)
		{
			GameWorldBase::HarborPos  p = {i%width,i/width};
			harbor_pos.push_back(p);
		}
	}

	// Katapultsteine deserialisieren
	sgd->PopObjectList(catapult_stones,GOT_CATAPULTSTONE);

	// Meeresinformationen deserialisieren
	seas.resize(sgd->PopUnsignedInt());
	for(unsigned i = 0;i<seas.size();++i)
	{
		seas[i].nodes_count = sgd->PopUnsignedInt();
	}

	// Hafenpositionen serialisieren
	harbor_pos.resize(sgd->PopUnsignedInt());
	for(unsigned i = 0;i<harbor_pos.size();++i)
	{
		harbor_pos[i].x = sgd->PopUnsignedShort();
		harbor_pos[i].y = sgd->PopUnsignedShort();
		for(unsigned z = 0;z<6;++z)
			harbor_pos[i].cps[z].sea_id = sgd->PopUnsignedShort();
		for(unsigned z = 0;z<6;++z)
		{
			harbor_pos[i].neighbors[z].resize(sgd->PopUnsignedInt());
			for(unsigned c = 0;c<harbor_pos[i].neighbors[z].size();++c)
			{
				harbor_pos[i].neighbors[z][c].id = sgd->PopUnsignedInt();
				harbor_pos[i].neighbors[z][c].distance = sgd->PopUnsignedInt();
			}
		}
	}

	sgd->PopObjectList<noBuildingSite>(harbor_building_sites_from_sea,GOT_BUILDINGSITE);

	// BQ neu berechnen
	for(unsigned y = 0;y<height;++y)
	{
		for(unsigned x = 0;x<width;++x)
		{
			SetBQ(x,y,GAMECLIENT.GetPlayerID());
		}
	}

	tr.GenerateOpenGL(this);

	// Zum HQ am Anfang springen, falls dieses existiert
	if(GetPlayer(GameClient::inst().GetPlayerID())->hqx != 0xFFFF)
		this->MoveToMapObject(GetPlayer(GameClient::inst().GetPlayerID())->hqx,
			GetPlayer(GameClient::inst().GetPlayerID())->hqy);
}