void CThreatMap::AddEnemyUnit(const EnemyUnit& e, const float scale) { const int posx = e.pos.x / (SQUARE_SIZE * THREATRES); const int posy = e.pos.z / (SQUARE_SIZE * THREATRES); assert(!threatCellsRaw.empty()); if (!MAPPOS_IN_BOUNDS(e.pos)) { std::stringstream msg; msg << "[CThreatMap::AddEnemyUnit][frame=" << ai->cb->GetCurrentFrame() << "][scale=" << scale << "]\n"; msg << "\tposition <" << e.pos.x << ", " << e.pos.z << "> of unit " << e.id; msg << " (health " << ai->ccb->GetUnitHealth(e.id) << ") is out-of-bounds\n"; ai->GetLogger()->Log(msg.str()); } const float threat = e.threat * scale; const float rangeSq = e.range * e.range; for (int myx = int(posx - e.range); myx < (posx + e.range); myx++) { if (myx < 0 || myx >= width) { continue; } for (int myy = int(posy - e.range); myy < (posy + e.range); myy++) { if (myy < 0 || myy >= height) { continue; } const int dxSq = (posx - myx) * (posx - myx); const int dySq = (posy - myy) * (posy - myy); if ((dxSq + dySq - 0.5) <= rangeSq) { assert((myy * width + myx) < threatCellsRaw.size()); assert((myy * width + myx) < threatCellsVis.size()); // MicroPather cannot deal with negative costs // (which may arise due to floating-point drift) // nor with zero-cost nodes (see MP::SetMapData, // threat is not used as an additive overlay) threatCellsRaw[myy * width + myx] = std::max(threatCellsRaw[myy * width + myx] + threat, THREATVAL_BASE); threatCellsVis[myy * width + myx] = std::max(threatCellsVis[myy * width + myx] + threat, THREATVAL_BASE); currSumThreat += threat; } } } currAvgThreat = currSumThreat / area; }
bool CPathFinder::IsPositionReachable(const MoveData* md, const float3& pos) const { if (md == 0) { // aircraft or building return true; } if (!MAPPOS_IN_BOUNDS(pos)) { return false; } const float* hgtMap = ai->cb->GetHeightMap(); const float* slpMap = ai->cb->GetSlopeMap(); const int WH = ai->cb->GetMapWidth(); const int WS = WH >> 1; const int xh = (pos.x / SQUARE_SIZE); const int zh = (pos.z / SQUARE_SIZE); const int xs = xh >> 1; const int zs = zh >> 1; bool heightOK = false; bool slopeOK = false; switch (md->moveFamily) { case MoveData::Ship: { heightOK = (hgtMap[zh * WH + xh] < -md->depth); slopeOK = true; } break; case MoveData::Tank: case MoveData::KBot: { heightOK = (hgtMap[zh * WH + xh] > -md->depth); slopeOK = (slpMap[zs * WS + xs] < md->maxSlope); } break; case MoveData::Hover: { heightOK = true; slopeOK = (slpMap[zs * WS + xs] < md->maxSlope); } break; } return (heightOK && slopeOK); }