Example #1
0
  //
  // Initialize system
  //
  void Init(Bool editModeIn)
  {
    ASSERT(!sysInit);

    editMode = editModeIn;

    U16 initialVal = U16(0);

    ASSERT(WorldCtrl::CellMapX());
    ASSERT(WorldCtrl::CellMapZ());

    // Initialise arrays
    for (U32 t = 0; t < Game::MAX_TEAMS; t++)
    {
      teamRemap[t]      = Game::MAX_TEAMS;
      invTeamRemap[t]   = Game::MAX_TEAMS;
      teamDirtyClust[t] = NULL;
      teamLastRescan[t] = U32_MAX;
    }

    if (editMode)
    {
      // If we're in the editor, setup for all teams
      teamCount = Game::MAX_TEAMS;

      for (U32 t = 0; t < Game::MAX_TEAMS; t++)
      {
        teamRemap[t] = U8(t);
        invTeamRemap[t] = U8(t);
      }
    }
    else
    {
      teamCount = Team::NumTeams();

      // Fill in remap entries for teams with id's
      for (U32 t = 0, t2 = 0; t < Game::MAX_TEAMS; t++)
      {
        Team *teamPtr = Team::Id2Team(t);

        if (teamPtr)
        {
          ASSERT(teamPtr->GetId() < Game::MAX_TEAMS)

          // Map team id back to sequential index
          teamRemap[teamPtr->GetId()] = U8(t2);

          // Map sequential team index to team id
          invTeamRemap[t2] = U8(teamPtr->GetId());

          ++t2;
        }
      }
      ASSERT(t2 == teamCount)
    }

    #ifdef DEVELOPMENT
    {
      // Log remap tables and test sync
      char s1[Game::MAX_TEAMS+1];
      char s2[Game::MAX_TEAMS+1];

      s1[Game::MAX_TEAMS] = s2[Game::MAX_TEAMS] = 0;
      for (U32 i = 0; i < Game::MAX_TEAMS; i++)
      {
        s1[i] = teamRemap[i] < Game::MAX_TEAMS ? char(teamRemap[i] + '0') : '.';
        s2[i] = invTeamRemap[i] < Game::MAX_TEAMS ? char(invTeamRemap[i] + '0') : '.';
      }

      //LOG_DIAG(("SightRemap [%s] [%s]", s1, s2))
      SYNC("SightRemap [" << s1 << "] [" << s2 << ']')
    }
    #endif

    // Allocate seeing array
    for (U32 level = 0; level < Map::LV_MAX; ++level)
    {
      for (U32 team = 0; team < teamCount; ++team)
      {
        seeMap[level][team] = new U16*[WorldCtrl::CellMapZ()];
        seeMap[level][team][0] = new U16[WorldCtrl::CellMapX() * WorldCtrl::CellMapZ()];

        for (U32 i = 1; i < WorldCtrl::CellMapZ(); ++i)
        {
          seeMap[level][team][i] = &seeMap[level][team][i - 1][WorldCtrl::CellMapX()];
        }

        // Set initial fog value for all tiles
        for (U32 z = 0; z < WorldCtrl::CellMapZ(); ++z)
        {
          for (U32 x = 0; x < WorldCtrl::CellMapX(); ++x)
          {
            seeMap[level][team][z][x] = initialVal;
          }
        }
      }
    }

    // Round x clusters up to the nearest 8 for the bit array
    mapClustXon8 = ((WorldCtrl::ClusterMapX() + 7) & (~7)) >> 3;

    // Allocate cluster update array
    displayDirtyCells = new BitArray2d(WorldCtrl::CellMapX(), WorldCtrl::CellMapZ());

    for (t = 0; t < teamCount; t++)
    {
      // Allocate team cluster update array
      teamDirtyClust[t] = new U8[mapClustXon8 * WorldCtrl::ClusterMapZ()];

      // Undirty all clusters
      memset(teamDirtyClust[t], 0, mapClustXon8 * WorldCtrl::ClusterMapZ());
    }

    // Initialise radius division lookup table
    for (U32 r = 0; r < MAXR; ++r)
    {
      invRadTbl[r] = (r == 0) ? 10000.0F : (1.0F / F32(r * WC_CELLSIZE));
    }

    // Initialise the terrain - set it all to shrouded
    SetAllFog(Terrain::fogFactorsS32[0]);

    // Create varsys commands
    VarSys::RegisterHandler("coregame.sight", CmdHandler);

    #ifdef DEVELOPMENT

    // Development commands
    VarSys::CreateCmd("coregame.sight.info");
    VarSys::CreateCmd("coregame.sight.map");
    VarSys::CreateInteger("coregame.sight.debugmode", FALSE, VarSys::DEFAULT, &debugMode);
    VarSys::CreateInteger("coregame.sight.debugscan", FALSE, VarSys::DEFAULT, &debugScan);

    #endif

   
    // The update rate of LOS display   moved to terrain.shroud.rate
//    VarSys::CreateInteger("coregame.sight.updaterate", 2, VarSys::DEFAULT, &displayRate);
//    displayRate->SetIntegerRange(0, 100);

    #ifdef DEVELOPMENT

    sweepTime.Reset();
    unSweepTime.Reset();
    updateDisp.Reset();
    dirtyCellTime.Reset();

    #endif

    // Should all units be visible?
    showAllUnits = FALSE;

    // System is initialised
    sysInit = TRUE;
  }
Example #2
0
  //
  // CellCostHeuristic
  //
  // Calculates the actual cost of moving from cell A to cell B.  Returns FALSE
  // if transition is impassable, otherwise returns TRUE and cost value.
  // Should be consistent with the estimation heuristic above.
  //
  static Bool CellCostHeuristic
  (
    S32 s, U32 ax, U32 az, U32 bx, U32 bz, 
    FootPrint::Instance *footInstance, FootPrint::Type::Cell *footCell, U16 &cost
  )
  { 
    // Is the destination blocked
    if (data.blockArray->Get2(bx, bz))
    {
      return (FALSE);
    }

    // Is source a second layer cell
    if (footCell)
    {
      ASSERT(footInstance);

      // Can we travel from a->b in this direction
      if (!footCell->CheckDir(RotateSuccessor(footInstance->GetDir(), s)))
      {
        return (FALSE);
      }
    }

    // Now check the destination cell
    if (TerrainData::UseSecondLayer(bx, bz))
    {
      footInstance = &TerrainData::GetFootPrintInstance(bx, bz);
      footCell = &footInstance->GetTypeCell(bx, bz);
      
      // Can we travel from b->a in this direction
      if (!footCell->CheckDir(RotateSuccessor(footInstance->GetDir(), SuccessorOpposite(s))))
      {
        return (FALSE);
      }
    }

    // Get the destination data cell
    TerrainData::Cell &bDataCell = TerrainData::GetCell(bx, bz);

    // Get the balance info
    MoveTable::BalanceData &d = MoveTable::GetBalance
    (
      bDataCell.surface, data.request.tractionType
    );

    // Call above method
    if (CanMoveToCell(d, bDataCell))
    {
      // Get base cost value for this cell
      U16 base = (U16)((ax == bx || az == bz) ? 10 : 14);

      // Set the cost based on the speed of this traction over this cell
      cost = U16(base + (2 * U16(base * (1.0F - d.speed))));

      // If we have a unit, check to see how much enemy 
      // threat there is to this unit in the current cluster 
      // and factor that into the cost
      if (data.request.unit.Alive())
      {
        // Get the cluster from the cell
        MapCluster *cluster = WorldCtrl::CellsToCluster(bx, bz);

        Team *team = data.request.unit->GetTeam();
        U32 ac = data.request.unit->UnitType()->GetArmourClass();

        // How much threat is there to this unit ?
        U32 threat = cluster->ai.EvaluateThreat(team, Relation::ENEMY, ac);
        cost = U16(Clamp<U32>(0, threat + cost, U16_MAX >> 2));

        // How much relative pain is there to this unit ?
        U32 pain = cluster->ai.GetPain(team->GetId(), ac);
        U32 totalPain = AI::Map::GetPain(team->GetId(), ac);

        if (totalPain)
        {
          if (totalPain == pain)
          {
            cost = U16(Clamp<U32>(0, cost + (U32_MAX >> 18), U16_MAX >> 2));
          }
          else
          {
            cost = U16(Clamp<U32>(0, cost + (Utils::Div(pain, 0, totalPain) >> 18), U16_MAX >> 2));
          }
        }
Example #3
0
    //
    // New and improved sweep
    //
    void Sweep(UnitObj *u)
    {
      ASSERT(sysInit);
      ASSERT(u);
      //ASSERT(u->GetTeam());
      ASSERT(u->OnMap());

      START(sweepTime);

      r = u->GetSeeingRange();
      unit = u;
      cellX = u->cellX;
      cellZ = u->cellZ;

      ASSERT(r < MAXR)

      // Get sight map and mask
      maskLo = u->sightMap->GetBitMask(Map::LV_LO);
      mapLo = u->sightMap->GetByteMap(Map::LV_LO);

      // Reset max radius seen
      u->sightMap->lastR = S16_MIN;

      // Set teams that this sweep will provide LOS for
      Team *myTeam = u->GetTeam();
      teamBits = 0;

      if (myTeam)
      {
        for (U32 team = 0; team < Game::MAX_TEAMS; ++team)
        {
          Team *other = Team::Id2Team(team);

          if (other)
          {
            if
            (
              // Other team is an ally
              Team::TestUnitRelation(u, other, Relation::ALLY)

              ||

              // Other team is giving us line of sight
              myTeam->GivingSightTo(other->GetId())
            )
            {
              ASSERT(teamRemap[team] < teamCount)
              Game::TeamSet(teamBits, teamRemap[team]);
            }
          }
        }
      }

      // Dirty cells that line of sight has changed in
      DirtyCells(cellX - r, cellZ - r, cellX + r, cellZ + r, teamBits);

      // Set up viewing radius
      if (r > 0)
      {
        r2 = r * r;
        r2Inv = 1.0f / F32(r2);

        // Get eye position
        eyePos = EyePosition(u);

        // In the code below the row and column of cells with the
        // same y and x value of the unit are processed twice but
        // their viewing information is only updated once. Stuff
        // the slight inneficiency (2*r extra comparisons). This
        // way we require 1/4 the memory and the code is more
        // elegant.

        // scan ++ quadrant
        quadrantX = POS;
        quadrantZ = POS;

        FillGradMap();
        FillMaxGradMapPosZ();
        CompareGradPosPos();

        // Scan -+ quadrant
        quadrantX = NEG;

        FillGradMapRotated();
        FillMaxGradMapPosZ();
        CompareGradNegPos();

        // Scan -- quadrant
        quadrantZ = NEG;

        FillGradMap();
        FillMaxGradMapNegZ();
        CompareGradNegNeg();

        // Scan +- quadrant
        quadrantX = POS;

        FillGradMapRotated();
        FillMaxGradMapNegZ();
        CompareGradPosNeg();
      }

      // Can always see cell that unit is occupying
      CanSee(cellX, cellZ, 0, 0, mapLo, maskLo, teamBits, Map::LV_LO);

      // Update scan info in unit's sight map
      u->sightMap->lastTeam = teamBits;
      u->sightMap->lastR = S16(r);
      u->sightMap->lastX = cellX;
      u->sightMap->lastZ = cellZ;
      u->sightMap->lastAlt = eyePos;

      STOP(sweepTime);
    }