Example #1
0
creature_t* creature_t::get_closest_enemy() const
{
  int x = pos.x;
  int y = pos.y;
  creature_t* closest_enemy = nullptr;
  int smallest_distance = INT_MAX;
  for (size_t i = 0; i < current_dungeon->creatures.size(); i++)
  {
    creature_t* possible_enemy = current_dungeon->creatures.at(i);
    int cx = possible_enemy->pos.x;
    int cy = possible_enemy->pos.y;
    int dist = (x - cx) * (x - cx) + (y - cy) * (y - cy);
    if (( possible_enemy->is_friendly() && !is_ally() ) ||
        (!possible_enemy->is_friendly() && ((identity == IDENT_PLAYER) || is_ally())))
    {
      if (dist < smallest_distance)
      {
        closest_enemy = possible_enemy;
        smallest_distance = dist;
      }
    }
  }

  return closest_enemy;
}
Example #2
0
void world::spawn_bullet(const char *type, const vec3 &pos, const vec3 &dir, const plane_ptr &owner)
{
    vec3 r;
    const bool hit_world = m_phys_world.spawn_bullet(type, pos, dir, r);

    if (!owner->net || owner->net->source)
    {
        for (auto &p: m_planes)
        {
            if (p->hp <= 0 || is_ally(owner, p))
                continue;

            if (line_sphere_intersect(pos, r, p->get_pos(), p->hit_radius))
            {
                p->take_damage(60, *this);
                const bool destroyed = p->hp <= 0;
                if (destroyed)
                    on_kill(owner, p);

                if (owner == get_player())
                    popup_hit(destroyed);
            }
        }
    }

    if (hit_world)
    {
        //ToDo: spark
    }
}
Example #3
0
void creature_t::try_move(int move_x, int move_y)
{
  tile_t* tile = get_tile_at(current_dungeon, move_x, move_y);
  if (tile && (tile_is_walkable_by(*tile, this)))
  {
    creature_t* thing = get_creature_at(current_dungeon, move_x, move_y);
    if (thing)
    {
      if (get_active_effects_for(this) & EF_CONFUSE)
      {
        creature_attacks(this, thing);
      }
      else if ((is_ally() && !thing->is_ally()) || (!is_ally() && thing->is_ally()))
      {
        // The two creatures are enemies.
        creature_attacks(this, thing);
      }
    }
    else if (player.pos.x == move_x && player.pos.y == move_y)
    {
      if (!is_friendly() || (get_active_effects_for(this) & EF_CONFUSE))
      {
        // Not ally with player, or confused.
        creature_attacks(this, &player);
      }
    }
    else
    {
      pos.x = move_x;
      pos.y = move_y;
    }
  }
  else if (tile && tile->id == TILE_DOOR_CLOSED)
  {
    if (flag & CF_INTELLIGENT)
    {
      open_door(current_dungeon, this, move_x, move_y);
      //creature->pos.x = move_x;
      //creature->pos.y = move_y;
    }
  }
}
void team_deathmatch::on_kill(const object_ptr &k, const object_ptr &v)
{
    auto vp = m_world.get_plane(v);
    if (!vp)
        return;

    auto kp = m_world.get_plane(k);
    if (kp)
    {
        if (!is_ally(kp, vp))
            kp->net_game_data.set("score", kp->net_game_data.get<int>("score") + 1);
    }
    else
        vp->net_game_data.set("score", vp->net_game_data.get<int>("score") - 1);
}
Example #5
0
bool GarrisonAbility::can_invoke(Unit &to_modify, const Command &cmd) {
	if (!cmd.has_unit()) {
		return false;
	}
	Unit &target = *cmd.unit();

	// make sure buildings are completed
	if (target.has_attribute(attr_type::building)) {
		auto &build_attr = target.get_attribute<attr_type::building>();
		if (build_attr.completed < 1.0f) {
			return false;
		}
	}
	return to_modify.location &&
	       target.has_attribute(attr_type::garrison) &&
	       is_ally(to_modify, target);
}
void unit_vehicle::update(int dt, world &w)
{
    if (hp <= 0)
        return;

    if (m_first_update)
    {
        m_first_update = false;

        if (!m_follow.expired())
        {
            auto f = m_follow.lock();
            vec3 diff = get_pos() - f->get_pos();
            if (diff.length() < m_params.formation_radius)
                m_formation_offset = f->get_rot().rotate_inv(diff);
            else
                m_formation_offset.set(0, 0, -15.0f);
        }

        m_ground = (get_pos().y - w.get_height(get_pos().x, get_pos().z)) < 5.0f;
        if (m_ground)
        {
            //ToDo: gear anim
        }
        else
        {
            if (m_params.speed_min > 0.01f)
                m_vel = get_rot().rotate(vec3::forward() * m_params.speed_cruise);
            m_dpos = vec3();
        }

        return;
    }

    float kdt = dt * 0.001f;

    vec3 target_dir;
    bool has_target = false;

    if (m_target.expired())
    {
        if (m_ai > ai_default && m_target_search != search_none)
        {
            const bool air = m_ai == ai_air_to_air || m_ai == ai_air_multirole,
            ground = m_ai == ai_air_to_ground || m_ai == ai_air_multirole;

            float min_dist = 10000.0f;
            for (int i = 0; i < w.get_planes_count() + w.get_units_count(); ++i)
            {
                object_ptr t;
                if (i < w.get_planes_count())
                {
                    auto p = w.get_plane(i);
                    if (is_ally(p, w))
                        continue;

                    t = p;
                }
                else
                {
                    if (m_target_search == search_player)
                        continue;

                    auto u = w.get_unit(i - w.get_planes_count());
                    if (is_ally(u))
                        continue;

                    t = u;
                }

                if (!t->is_targetable(air, ground))
                    continue;

                const float dist = (t->get_pos() - get_pos()).length();
                if(dist >= min_dist)
                    continue;

                m_target = t;
                min_dist = dist;
            }
        }
    }
    else
    {
        if (m_target.lock()->hp <= 0)
            m_target.reset();
    }

    bool not_path_not_follow = false;

    if (!m_path.empty())
    {
        has_target = true;
        target_dir = m_path.front() - get_pos();
        if (target_dir.length() < m_vel.length() * kdt * m_params.target_radius)
        {
            if (m_path_loop)
                m_path.push_back(m_path.front());
            m_path.pop_front();
            if (m_path.empty())
                has_target = false;
            else
                target_dir = m_path.front() - get_pos();
        }
    }
    else if (!m_follow.expired())
    {
        has_target = true;
        auto f = m_follow.lock();
        target_dir = f->get_pos() + f->get_rot().rotate(m_formation_offset) - (get_pos() + get_vel() * kdt);
        //+ f->get_vel() * kdt //player's plane is already updated, ToDo
    }
    else
        not_path_not_follow = true;

    if (!m_target.expired())
    {
        auto t = m_target.lock();
        const auto dir = t->get_pos() + t->get_rot().rotate(vec3(0, 0, -20.0)) - (get_pos() + get_vel() * kdt);

        if (not_path_not_follow)
        {
            target_dir = dir;
            has_target = true;
        }

        for (auto &wp: m_weapons)
        {
            if (wp.cooldown > 0)
            {
                wp.cooldown -= dt;
                continue;
            }

            if (dir.length() > wp.params.lockon_range)
                continue;

            wp.cooldown = wp.params.reload_time;
            auto m = w.add_missile(wp.params.id.c_str(), wp.mdl);
            if (!m)
                continue;

            m->phys->pos = get_pos();
            m->phys->rot = get_rot();
            m->phys->vel = get_vel();

            m->phys->target_dir = dir;
            m->target = m_target;
        }
    }

    if (has_target)
    {
        const float eps=1.0e-6f;
        const float target_dist = target_dir.length();
        const vec3 v=target_dir / target_dist;
        const float xz_sqdist=v.x*v.x+v.z*v.z;

        const auto rot = get_rot();
        const auto pyr = rot.get_euler();

        const nya_math::angle_rad new_yaw=(xz_sqdist>eps*eps)? (atan2(v.x,v.z)) : pyr.y;
        nya_math::angle_rad new_pitch=(fabsf(v.y)>eps)? (-atan2(v.y,sqrtf(xz_sqdist))) : 0.0f;
        nya_math::angle_rad new_roll;
        if (!m_follow.expired())
            new_roll = m_follow.lock()->get_rot().get_euler().z;

        vec3 pos = get_pos() + m_vel * kdt;
        const float h = w.get_height(pos.x, pos.z);
        if ((new_pitch > 0.0f && pos.y <= h + m_params.height_min) || (new_pitch < 0.0f && pos.y >= h + m_params.height_max))
            new_pitch = 0.0f;

        const auto ideal_rot = quat(new_pitch, new_yaw, new_roll);

        const float angle_diff = rot.rotate(vec3::forward()).angle(target_dir).get_deg();
        if (fabsf(angle_diff) > 0.001f)
        {
            const float turn_k = nya_math::clamp((180.0f / angle_diff) * m_params.turn_speed * kdt, 0.0, 1.0);
            m_render->mdl.set_rot(quat::slerp(rot, ideal_rot, turn_k));
        }

        float speed = m_vel.length();
        float want_speed = target_dist / kdt;
        if (!m_follow.expired())
        {
            const float target_speed = m_follow.lock()->get_vel().length();
            float decel_time = (speed - target_speed) / m_params.decel;
            if (target_dist / (speed + m_params.accel * kdt) < decel_time)
                want_speed = target_speed;
        }

        want_speed = nya_math::clamp(want_speed, m_params.speed_min, std::min(m_params.speed_max, m_speed_limit));
        speed = tend(speed, want_speed, m_params.accel * kdt, m_params.decel * kdt);
        m_vel = get_rot().rotate(vec3(0.0, 0.0, speed));
    }
    else if (m_params.speed_min < 0.01f)
    {
        float speed = m_vel.length();
        if (speed > 0.0f)
        {
            speed = tend(speed, 0.0f, m_params.accel * kdt, m_params.decel * kdt);
            m_vel = get_rot().rotate(vec3(0.0, 0.0, speed));
        }
    }

    vec3 pos = get_pos() + m_vel * kdt;

    const float h = w.get_height(pos.x, pos.z);
    pos.y = nya_math::clamp(pos.y, h + m_params.height_min, h + m_params.height_max); //ToDo

    set_pos(pos);
}
Example #7
0
void FightEvent::run()
{
  // store all the fighters except the users
  std::vector<Fighter*> all_fighters;
  
  for (int i = 0; i < static_cast<int>(allies.size()); ++i)
    all_fighters.push_back(allies.at(i));
  
  for (int i = 0; i < static_cast<int>(enemies.size()); ++i)
    all_fighters.push_back(enemies.at(i));
  
  // sort from fastest to slowest
  std::sort(all_fighters.begin(), all_fighters.end(), comp_speed);
  
  // find the correct index to insert the user's ship
  int i = 0;
  for (; i < static_cast<int>(all_fighters.size()) && all_fighters.at(i)->get_base_speed() > get_modified_speed(); ++i);
  
  if (i == static_cast<int>(all_fighters.size()))
    all_fighters.push_back(player->get_ship());
  
  else
    all_fighters.insert(all_fighters.begin() + i, player->get_ship());

  int round = 1;
  
  // fight until user's ship destroyed or no more enemies left
  while (get_modified_health() > 0 && enemies.size() > 0)
  {
    usleep(3000000);
    
    utilities::clear_display();
    
    std::cout << "\n==== Fight Round " << round << " ====\n\n";
    
    // let each fighter have a chance to fight
    for (int j = 0; j < static_cast<int>(all_fighters.size()) && get_modified_health() > 0 && enemies.size() > 0; ++j)
    {
      Fighter* cur_fighter = all_fighters.at(j);
      
      // fighter is dead
      if (!is_ally(cur_fighter) && !is_enemy(cur_fighter))
      {
        all_fighters.erase(all_fighters.begin() + j);
        delete cur_fighter;
        cur_fighter = NULL;
        
        // adjust index based on the removed fighter
        j--;
      }
      
      // fighter is still alive and can attack
      else
      {
        int area_wide_attk = 0;
        int reg_attk = 0;
        
        // user gets to attack
        if (cur_fighter == player->get_ship())
        {
          // only one of these can be non-zero
          area_wide_attk = cur_fighter->is_area_wide() ? get_modified_attack() : 0;
          reg_attk = cur_fighter->is_area_wide() ? 0 : get_modified_attack();
          
          // do attack affecting all enemies
          if (area_wide_attk > 0)
            attack_area(cur_fighter, PLAYER, area_wide_attk, enemies);
          
          // do attack targeting a single enemy
          else if (reg_attk > 0)
          {
            // attack a random enemy
            int who_attacked = rand() % enemies.size();
            Fighter *attacked = enemies.at(who_attacked);

            attack_one(cur_fighter, PLAYER, reg_attk, attacked, enemies, who_attacked);
          }
        }
        
        // ally is attacking the enemies
        else if (is_ally(cur_fighter))
        {
          // only one of these can be non-zero
          area_wide_attk = cur_fighter->attack_enemies();
          reg_attk = cur_fighter->attack_enemy();
          
          // do attack affecting all enemies
          if (area_wide_attk > 0)
            attack_area(cur_fighter, AL, area_wide_attk, enemies);
          
          // do attack targeting a single enemy
          else if (reg_attk > 0)
          {
            // attack a random enemy
            int who_attacked = rand() % enemies.size();
            Fighter *attacked = enemies.at(who_attacked);
            
            attack_one(cur_fighter, AL, reg_attk, attacked, enemies, who_attacked);
          }
        }
        
        // enemy is attacking you and your allies
        else
        {
          // only one of these can be non-zero
          area_wide_attk = cur_fighter->attack_enemies();
          reg_attk = cur_fighter->attack_enemy();
          
          // do attack affecting all allies and user
          if (area_wide_attk > 0)
            attack_area(cur_fighter, EN, area_wide_attk, allies);
          
          // do attack targeting a single ally or the user
          else if (reg_attk > 0)
          {
            // attack a random ally
            int who_attacked = 0;
            
            if (allies.size() > 0)
              who_attacked = rand() % allies.size() + 1;
            
            // user's ship was attacked
            if (who_attacked == static_cast<int>(allies.size()))
            {
              const int IGNORE = -1;
              attack_one(cur_fighter, EN, reg_attk, player->get_ship(), allies, IGNORE);
            }
            
            // ally's ship was attacked
            else
            {
              Fighter *attacked = allies.at(who_attacked);
              
              attack_one(cur_fighter, EN, reg_attk, attacked, allies, who_attacked);
            }
          }
        }
      }
    }
    
    // next fight round
    ++round;
  }
  
  std::cout << std::endl;
  
  // clean up all the pointers of ships that weren't defeated
  for (int m = 0; m < static_cast<int>(all_fighters.size()); ++m)
  {
    Fighter *cur = all_fighters.at(m);
    
    if (cur != player->get_ship())
    {
      delete cur;
      cur = NULL;
    }
  }
  
  if (get_modified_health() > 0)
  {
    std::cout << "You managed to survive with " << get_modified_health() << " health!\n\n";
    
    int winnings = rand() % 400 + 1;
    std::cout << "You came up on " << winnings << " ducats!\n\n";
    
    player->gain_money(winnings);
    player->won_battle();
  }
  
  else
  {
    std::cout << "Darn!  You died.  Game over!\n\n";
    player->died();
  }
}