/// erzeugt Rand-Vertex void TerrainRenderer::UpdateBorderVertex(const MapPoint pt, const GameWorldViewer& gwv) { /// @todo GetTerrainX und Co durch GetTerrainXA ausdrücken Vertex& vertex = GetVertex(pt); vertex.borderPos[0] = ( GetTerrainAround(pt, 5) + GetTerrain(pt) + GetTerrainAround(pt, 4) ) / 3.0f; vertex.borderColor[0] = ( GetColor(gwv.GetNeighbour(pt, 5)) + GetColor(pt) + GetColor(gwv.GetNeighbour(pt, 4)) ) / 3.0f; vertex.borderPos[1] = ( GetTerrainAround(pt, 3) + GetTerrain(pt) + GetTerrainAround(pt, 4) ) / 3.0f; vertex.borderColor[1] = ( GetColor(gwv.GetNeighbour(pt, 3)) + GetColor(pt) + GetColor(gwv.GetNeighbour(pt, 4)) ) / 3.0f; }
/// Gibt zurück, ob ein Punkt vollständig von Wasser umgeben ist bool GameWorldBase::IsSeaPoint(MapCoord x, MapCoord y) const { for(unsigned i = 0;i<6;++i) { if(GetTerrainAround(x,y,i) != TT_WATER) return false; } return true; }
void TerrainRenderer::UpdateTrianglePos(const MapPoint pt, const GameWorldViewer& gwv, const bool update) { unsigned int pos = GetTriangleIdx(pt); gl_vertices[pos][0] = GetTerrainAround(pt, 4); gl_vertices[pos][1] = GetTerrain(pt); gl_vertices[pos][2] = GetTerrainAround(pt, 5); ++pos; gl_vertices[pos][0] = GetTerrain(pt); gl_vertices[pos][1] = GetTerrainAround(pt, 4); gl_vertices[pos][2] = GetTerrainAround(pt, 3); if(update && vboBuffersUsed) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_vertices); glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, (pos - 1) * sizeof(Triangle), 2 * sizeof(Triangle), &gl_vertices[pos - 1]); } }
/** * Gibt das Terrain zurück, über das ein Mensch/Tier laufen müsste, von X,Y * in Richtung DIR (Rückwärts). * * @author OLiver */ unsigned char GameWorldBase::GetWalkingTerrain2(MapCoord x, MapCoord y, unsigned char dir) const { assert(dir < 6); switch(dir) { case 0: return GetTerrainAround(x,y,0); case 1: return GetTerrainAround(x,y,1); case 2: return GetTerrainAround(x,y,2); case 3: return GetTerrainAround(x,y,3); case 4: return GetTerrainAround(x,y,4); case 5: return GetTerrainAround(x,y,5); } return 0xFF; }
BuildingQuality GameWorldBase::CalcBQ(const MapCoord x, const MapCoord y,const unsigned char player,const bool flagonly,const bool visual, const bool ignore_player) const { /////////////////////// // 1. nach Terrain // Unser Land? if(!ignore_player && (GetNode(x,y).owner-1 != player || !IsPlayerTerritory(x,y))) return BQ_NOTHING; unsigned building_hits = 0; unsigned mine_hits = 0; unsigned flag_hits = 0; BuildingQuality val = BQ_CASTLE; unsigned char t; // bebaubar? for(unsigned char i = 0;i<6;++i) { t = GetTerrainAround(x,y,i); if(TERRAIN_BQ[t] == BQ_CASTLE) ++building_hits; else if(TERRAIN_BQ[t] == BQ_MINE) ++mine_hits; else if(TERRAIN_BQ[t] == BQ_FLAG) ++flag_hits; else if(TERRAIN_BQ[t] == BQ_DANGER) return BQ_NOTHING; } if(flag_hits) val = BQ_FLAG; else if(mine_hits == 6) val = BQ_MINE; else if(mine_hits) val = BQ_FLAG; else if(building_hits == 6) val = BQ_CASTLE; else if(building_hits) val = BQ_FLAG; else return BQ_NOTHING; ////////////////////////////////////// // 2. nach Terrain unsigned char ph = GetNode(x,y).altitude, th; // Bergwerke anders handhaben if(val == BQ_CASTLE && val != BQ_FLAG) { if((th=GetNodeAround(x,y,4).altitude) > ph) { if(th - ph > 1) val = BQ_FLAG; } // 2. Außenschale prüfen ( keine Hütten werden ab Steigung 3 ) for(unsigned i = 0;i<12;++i) { if( (th = GetNode(GetXA2(x,y,i),GetYA2(x,y,i)).altitude ) > ph) { if(th - ph > 2) { val = BQ_HUT; break; } } if( (th = GetNode(GetXA2(x,y,i), GetYA2(x,y,i)).altitude ) < ph) { if(ph - th > 2) { val = BQ_HUT; break; } } } // 1. Auäcnschale ( käcnen Flaggen werden ab Steigung 4) for(unsigned i = 0;i<6;++i) { if((th=GetNodeAround(x,y,i).altitude) > ph) { if(th - ph > 3) val = BQ_FLAG; } if((th=GetNodeAround(x,y,i).altitude) < ph) { if(ph - th > 3) val = BQ_FLAG; } } } else { for(unsigned i = 0;i<6;++i) { if(i > 3 && i!=5 && (th=GetNodeAround(x,y,i).altitude) > ph) { if(th - ph > 3) val = BQ_FLAG; } } } ////////////////////////////////////////// // 3. nach Objekten if(flagonly) if(FlagNear(x,y)) return BQ_NOTHING; // allgemein nix bauen auf folgenden Objekten: if(GetNO(x,y)->GetBM() != noBase::BM_NOTBLOCKING) return BQ_NOTHING; // Don't build anything around charburner piles for(unsigned i = 0;i<6;++i) { if(GetNO(GetXA(x,y,i),GetYA(x,y,i))->GetBM() == noBase::BM_CHARBURNERPILE) return BQ_NOTHING; } if(val > 2 && val != BQ_MINE) { for(unsigned i = 0;i<6;++i) { // Baum --> rundrum Hütte if(GetNO(GetXA(x,y,i),GetYA(x,y,i))->GetType() == NOP_TREE) { val = BQ_HUT; break; } /*// StaticObject --> rundrum Flagge/Hütte else if(GetNO(GetXA(x,y,i),GetYA(x,y,i))->GetType() == NOP_OBJECT) { const noStaticObject *obj = GetSpecObj<noStaticObject>(GetXA(x,y,i),GetYA(x,y,i)); if(obj->GetSize() == 2) val = BQ_FLAG; else val = BQ_HUT; break; }*/ } } // Stein, Feuer und Getreidefeld --> rundrum Flagge for(unsigned i = 0;i<6;++i) { const noBase * nob = GetNO(GetXA(x,y,i),GetYA(x,y,i)); if(nob->GetBM() == noBase::BM_GRANITE) { val = BQ_FLAG; break; } } // Flagge if(val == BQ_CASTLE) { for(unsigned char i = 0;i<3;++i) { if(GetNodeAround(x,y,i).obj) { if(GetNodeAround(x,y,i).obj->GetBM() == noBase::BM_FLAG) val = BQ_HOUSE; } } } if(GetNO(GetXA(x,y,3),GetYA(x,y,3))->GetBM() == noBase::BM_FLAG) return BQ_NOTHING; if(GetNO(GetXA(x,y,5),GetYA(x,y,5))->GetBM() == noBase::BM_FLAG) return BQ_NOTHING; if(val != BQ_FLAG) { if(GetNO(GetXA(x,y,5),GetYA(x,y,5))->GetBM() == noBase::BM_FLAG) val = BQ_FLAG; } // Gebäude if(val == BQ_CASTLE) { for(unsigned i = 0;i<12;++i) { noBase::BlockingManner bm = GetNO(GetXA2(x,y,i),GetYA2(x,y,i))->GetBM(); if(bm >= noBase::BM_HUT && bm <= noBase::BM_MINE) val = BQ_HOUSE; } } for(unsigned i = 0;i<3;++i) { if(val == BQ_CASTLE) { for(unsigned char c = 0;c<6;++c) { if(GetPointRoad(GetXA(x,y,i),GetYA(x,y,i), c, visual)) { val = BQ_HOUSE; break; } } } } for(unsigned char c = 0;c<6;++c) { if(GetPointRoad(x,y, c, visual)) { val = BQ_FLAG; break; } } if(val == BQ_FLAG) { for(unsigned char i = 0;i<6;++i) { if(GetNO(GetXA(x,y,i),GetYA(x,y,i))->GetBM() == noBase::BM_FLAG) return BQ_NOTHING; } } if(flagonly) return BQ_FLAG; if(val == BQ_FLAG) { for(unsigned char i = 0;i<3;++i) if(GetNO(GetXA(x,y,i),GetYA(x,y,i))->GetBM() == noBase::BM_FLAG) return BQ_NOTHING; } // Schloss bis hierhin und ist hier ein Hafenplatz? if(val == BQ_CASTLE && GetNode(x,y).harbor_id) // Dann machen wir einen Hafen draus val = BQ_HARBOR; if(val >= BQ_HUT && val <= BQ_HARBOR) { if(GetNO(GetXA(x,y,4),GetYA(x,y,4))->GetBM() == noBase::BM_FLAG) return val; if(CalcBQ(GetXA(x,y,4),GetYA(x,y,4),player,true,visual,ignore_player)) { return val; } else { for(unsigned char i = 0;i<3;++i) if(GetNO(GetXA(x,y,i),GetYA(x,y,i))->GetBM() == noBase::BM_FLAG) return BQ_NOTHING; return BQ_FLAG; } } return val; }
bool GameWorldBase::RoadAvailable(const bool boat_road,const int x, const int y,unsigned char to_dir,const bool visual) const { // Hindernisse if(GetNode(x,y).obj) { noBase::BlockingManner bm = GetNode(x,y).obj->GetBM(); if(bm != noBase::BM_NOTBLOCKING) return false; } //dont build on the border if(GetNode(x,y).boundary_stones[0]) return false; for(unsigned char z = 0;z<6;++z) { // Roads around charburner piles are not possible if(GetNO(GetXA(x,y,z),GetYA(x,y,z))->GetBM() == noBase::BM_CHARBURNERPILE) return false; // Other roads at this point? if(GetPointRoad(x,y, z, visual)) { (void) GetPointRoad(x,y, z, visual); return false; } } for(unsigned char i = 3;i<6;++i) { if(GetNO(GetXA(x,y,i),GetYA(x,y,i))->GetBM() == noBase::BM_CASTLE) return false; } // Terrain (unterscheiden, ob Wasser und Landweg) if(!boat_road) { unsigned flag_hits = 0; unsigned char t; for(unsigned char i = 0;i<6;++i) { t = GetTerrainAround(x,y,i); if(TERRAIN_BQ[t] == BQ_CASTLE || TERRAIN_BQ[t] == BQ_CASTLE || TERRAIN_BQ[t] == BQ_MINE || TERRAIN_BQ[t] == BQ_FLAG) ++flag_hits; else if(TERRAIN_BQ[t] == BQ_DANGER) return 0; } if(!flag_hits) return false; // Richtung übergeben? Dann auch das zwischen den beiden Punkten beachten, damit // man nicht über ein Wasser oder so hüpft if(to_dir != 0xFF) { // Richtung genau entgegengesetzt, da das ja hier der Zielpunkt ist, wir müssen wieder zurück zum Quellpunkt to_dir = (to_dir+3)%6; //// Nicht über Wasser, Lava, Sümpfe gehen //if(!IsNodeToNodeForFigure(x,y,to_dir,boat_road)) // return false; } return true; } else { // Beim Wasserweg muss um den Punkt herum Wasser sein for(unsigned i = 0;i<6;++i) if(GetTerrainAround(x,y,i) != 14) return false; } return true; }
/// Erzeugt die Dreiecke für die Ränder void TerrainRenderer::UpdateBorderTrianglePos(const MapPoint pt, const GameWorldViewer& gwv, const bool update) { unsigned int pos = GetVertexIdx(pt); // Für VBO-Aktualisierung: // Erzeugte Ränder zählen unsigned count_borders = 0; // Erstes Offset merken unsigned first_offset = 0; // Rand links - rechts for(unsigned char i = 0; i < 2; ++i) { if(!borders[pos].left_right[i]) continue; unsigned int offset = borders[pos].left_right_offset[i]; if(!first_offset) first_offset = offset; gl_vertices[offset][i ? 0 : 2] = GetTerrain(pt); gl_vertices[offset][1 ] = GetTerrainAround(pt, 4); gl_vertices[offset][i ? 2 : 0] = GetB(pt, i); ++count_borders; } // Rand rechts - links for(unsigned char i = 0; i < 2; ++i) { if(!borders[pos].right_left[i]) continue; unsigned int offset = borders[pos].right_left_offset[i]; if(!first_offset) first_offset = offset; gl_vertices[offset][i ? 2 : 0] = GetTerrainAround(pt, 4); gl_vertices[offset][1 ] = GetTerrainAround(pt, 3); if(i == 0) gl_vertices[offset][2] = GetB(pt, 1); else gl_vertices[offset][0] = GetBAround(pt, 0, 3); ++count_borders; } // Rand oben - unten for(unsigned char i = 0; i < 2; ++i) { if(!borders[pos].top_down[i]) continue; unsigned int offset = borders[pos].top_down_offset[i]; if(!first_offset) first_offset = offset; gl_vertices[offset][i ? 2 : 0] = GetTerrainAround(pt, 5); gl_vertices[offset][1 ] = GetTerrainAround(pt, 4); if(i == 0) gl_vertices[offset][2] = GetB(pt, i); else gl_vertices[offset][0] = GetBAround(pt, i, 5); //x - i + i * rt, y + i, i ++count_borders; } /// Bei Vertexbuffern das die Daten aktualisieren if(update && vboBuffersUsed) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_vertices); glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, first_offset * sizeof(Triangle), count_borders * sizeof(Triangle), &gl_vertices[first_offset]); } }