Esempio n. 1
0
	void UpdateEscortAI(const uint32 uiDiff) override
	{
		if (m_started && !m-creature->SelectHostileTarget())
		{
			if (m_creature->GetAreaId() == AREA_DRAGONMAW_FORTRESS)
			{
				Start(true);
				SetEscortPaused(true);
				SetCurrentWaypoint(12);
				SetEscortPaused(false);
				m_started = false;
			}
			else
			{
				Start(true);
				SetEscortPaused(true);
				SetCurrentWaypoint(1);
				SetEscortPaused(false);
				m_started = false;
			}
		}

		if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
			return;

		DoMeleeAttackIfReady();
	}
Esempio n. 2
0
    void ReceiveAIEvent(AIEventType eventType, Creature* /*pSender*/, Unit* pInvoker, uint32 uiMiscValue) override
    {
        if (eventType == AI_EVENT_START_ESCORT && pInvoker->GetTypeId() == TYPEID_PLAYER)
        {
            Start(true, (Player*)pInvoker, GetQuestTemplateStore(uiMiscValue));
            SetEscortPaused(true);

            // set alternative waypoints if required
            if (m_creature->GetPositionX() > 6650.0f)
                SetCurrentWaypoint(7);
            else if (m_creature->GetPositionX() > 6635.0f)
                SetCurrentWaypoint(35);

            DoScriptText(SAY_MINER_READY, m_creature);
            m_creature->SetStandState(UNIT_STAND_STATE_STAND);
            m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
            m_creature->RemoveAurasDueToSpell(SPELL_FEIGN_DEATH);
            m_creature->SetFactionTemporary(FACTION_ESCORT_N_FRIEND_ACTIVE, TEMPFACTION_RESTORE_RESPAWN);
        }
        else if (eventType == AI_EVENT_CUSTOM_A && pInvoker->GetTypeId() == TYPEID_PLAYER)
        {
            SetEscortPaused(false);
            m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
        }
    }
    void ReceiveAIEvent(AIEventType eventType, Creature* pSender, Unit* pInvoker, uint32 uiMiscValue) override
    {
        // on Malganis encounter finished -> evade
        if (pSender->GetEntry() == NPC_MALGANIS && eventType == AI_EVENT_CUSTOM_EVENTAI_B)
        {
            EnterEvadeMode();
            SetEscortPaused(false);
            return;
        }

        if (pInvoker->GetTypeId() != TYPEID_PLAYER)
            return;

        if (eventType == AI_EVENT_START_ESCORT)
        {
            DoScriptText(SAY_ARTHAS_FOLLOW, m_creature);
            Start(true, (Player*)pInvoker);
        }
        else if (eventType == AI_EVENT_CUSTOM_A)
        {
            DoScriptText(SAY_ARTHAS_QUICK_PATH, m_creature);
            SetEscortPaused(false);
        }
        else if (eventType == AI_EVENT_START_ESCORT_B)
        {
            // start and set WP
            Start(true, (Player*)pInvoker);
            SetEscortPaused(true);
            SetCurrentWaypoint(POINT_ID_ESCORT_CITY);
            SetEscortPaused(false);

            DoScriptText(SAY_ARTHAS_MOVE_QUICKLY, m_creature);
            m_creature->SetFactionTemporary(FACTION_ARTHAS_2, TEMPFACTION_RESTORE_REACH_HOME);

            if (m_pInstance)
                m_pInstance->DoSpawnBurningCityUndead(m_creature);
        }
        else if (eventType == AI_EVENT_CUSTOM_B)
        {
            // resume escort or start on point if start from reset
            if (HasEscortState(STATE_ESCORT_PAUSED))
                SetEscortPaused(false);
            else
            {
                Start(true, (Player*)pInvoker);
                SetEscortPaused(true);
                SetCurrentWaypoint(POINT_ID_MARKET_ROW);
                SetEscortPaused(false);
            }

            DoScriptText(SAY_ARTHAS_JUSTICE_DONE, m_creature);
            m_creature->SetFactionTemporary(FACTION_ARTHAS_2, TEMPFACTION_RESTORE_REACH_HOME);

            // spawn Malganis if required
            if (m_pInstance && !m_pInstance->GetSingleCreatureFromStorage(NPC_MALGANIS, true))
                m_creature->SummonCreature(NPC_MALGANIS, 2296.862F, 1501.015F, 128.445F, 5.13f, TEMPSPAWN_DEAD_DESPAWN, 0);
        }
    }
Esempio n. 4
0
    void JustRespawned()
    {
        if (!m_pInstance)
            return;

        Reset();

        if (m_pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS)
        {
            SetEscortPaused(true);

            m_bHadMount = false;
            DoUnmount();

            m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);

            // check current states before fail and set spesific for the part
            if (m_pInstance->GetData(TYPE_THRALL_PART1) == IN_PROGRESS)
            {
                SetCurrentWaypoint(1);                      // basement

                SetEquipmentSlots(true);
                m_creature->SetDisplayId(MODEL_THRALL_UNEQUIPPED);

                m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
            }
            else if (m_pInstance->GetData(TYPE_THRALL_PART2) == IN_PROGRESS)
            {
                SetCurrentWaypoint(61);                     // barn
                m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
            }
            else if (m_pInstance->GetData(TYPE_THRALL_PART3) == IN_PROGRESS || m_pInstance->GetData(TYPE_THRALL_PART4) == IN_PROGRESS)
                SetCurrentWaypoint(96);                     // inn

            // fail, and relocation handled in instance script
            m_pInstance->SetData(TYPE_THRALL_EVENT, FAIL);
        }
    }
Esempio n. 5
0
    // Wrapper to handle start function for both quests
    void StartEscort(Player* pPlayer, const Quest* pQuest)
    {
        m_creature->SetStandState(UNIT_STAND_STATE_STAND);
        m_creature->SetFacingToObject(pPlayer);
        m_uiQuestId = pQuest->GetQuestId();

        if (pQuest->GetQuestId() == QUEST_ESCAPE_THROUGH_STEALTH)
        {
            // Note: faction may not be correct, but only this way works fine
            m_creature->SetFactionTemporary(FACTION_FRIENDLY, TEMPFACTION_RESTORE_RESPAWN);

            Start(true, pPlayer, pQuest);
            SetEscortPaused(true);
            SetCurrentWaypoint(WAYPOINT_ID_QUEST_STEALTH);
            SetEscortPaused(false);
        }
        else
            Start(false, pPlayer, pQuest);
    }
Esempio n. 6
0
    // Respawn Handling: Relocate and Set Escort to WP 13
    void JustRespawned() override
    {
        if (!m_pInstance)
            return;

        Reset();

        if (m_pInstance->GetData(TYPE_TRIBUNAL) == IN_PROGRESS)
        {
            SetEscortPaused(true);

            m_uiStep = 0;
            m_uiPhaseTimer = 0;

            m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);

            // Relocate to position of WP 13
            m_creature->GetMap()->CreatureRelocation(m_creature, 941.101563f, 377.373413f, 207.421f, 3.85f);

            SetCurrentWaypoint(13);
        }
    }
Esempio n. 7
0
 void WaypointReached(uint32 uiPointId) override
 {
     switch (uiPointId)
     {
         case 33:
             DoScriptText(SAY_MINER_COMPLETE, m_creature);
             if (Player* pPlayer = GetPlayerForEscort())
             {
                 pPlayer->GroupEventHappens(QUEST_ID_BITTER_DEPARTURE, m_creature);
                 m_creature->SetFacingToObject(pPlayer);
             }
             break;
         case 34:
             m_creature->ForcedDespawn();
             break;
         case 46:
             // merge with the other wp path
             SetEscortPaused(true);
             SetCurrentWaypoint(13);
             SetEscortPaused(false);
             break;
     }
 }
WorldObjectWidget::WorldObjectWidget(QWidget *parent) :
  QWidget(parent),
  ui(new Ui::WorldObjectWidget)
{
  ui->setupUi(this);
  selection.object = 0;
  selection_type   = 0;
  UnsetSelection();

  ui->actionsButton->setMenu(&action_menu);

  connect(ui->objectName, SIGNAL(textChanged(QString)), this, SLOT(UpdateName(QString)));

  // Geometry
  connect(ui->objectPosX,        SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry()));
  connect(ui->objectPosY,        SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry()));
  connect(ui->objectPosZ,        SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry()));
  connect(ui->objectRotationX,   SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry()));
  connect(ui->objectRotationY,   SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry()));
  connect(ui->objectRotationZ,   SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry()));
  connect(ui->objectScaleX,      SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry()));
  connect(ui->objectScaleY,      SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry()));
  connect(ui->objectScaleZ,      SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry()));
  connect(ui->objectFloor,       SIGNAL(valueChanged(int)),    this, SLOT(UpdateFloor()));
  connect(ui->inheritsFloor,     SIGNAL(toggled(bool)),        this, SLOT(UpdateFloor()));

  // Collider
  connect(ui->displayColliders,  SIGNAL(toggled(bool)),            this, SLOT(UpdateColliderDisplay()));
  connect(ui->collider_type,     SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateColliderType()));
  connect(ui->collider_pos_x,    SIGNAL(valueChanged(double)),     this, SLOT(UpdateColliderGeometry()));
  connect(ui->collider_pos_y,    SIGNAL(valueChanged(double)),     this, SLOT(UpdateColliderGeometry()));
  connect(ui->collider_pos_z,    SIGNAL(valueChanged(double)),     this, SLOT(UpdateColliderGeometry()));
  connect(ui->collider_hpr_x,    SIGNAL(valueChanged(double)),     this, SLOT(UpdateColliderGeometry()));
  connect(ui->collider_hpr_y,    SIGNAL(valueChanged(double)),     this, SLOT(UpdateColliderGeometry()));
  connect(ui->collider_hpr_z,    SIGNAL(valueChanged(double)),     this, SLOT(UpdateColliderGeometry()));
  connect(ui->collider_scale_x,  SIGNAL(valueChanged(double)),     this, SLOT(UpdateColliderGeometry()));
  connect(ui->collider_scale_y,  SIGNAL(valueChanged(double)),     this, SLOT(UpdateColliderGeometry()));
  connect(ui->collider_scale_z,  SIGNAL(valueChanged(double)),     this, SLOT(UpdateColliderGeometry()));

  // Light
  connect(ui->lightSetEnabled,   SIGNAL(toggled(bool)),         this, SLOT(LightSetEnabled(bool)));
  connect(ui->lightSetDisabled,  SIGNAL(toggled(bool)),         this, SLOT(LightSetDisabled(bool)));
  connect(ui->lightColorR,       SIGNAL(valueChanged(double)),  this, SLOT(UpdateLightColor()));
  connect(ui->lightColorG,       SIGNAL(valueChanged(double)),  this, SLOT(UpdateLightColor()));
  connect(ui->lightColorB,       SIGNAL(valueChanged(double)),  this, SLOT(UpdateLightColor()));
  connect(ui->lightAttenuationA, SIGNAL(valueChanged(double)),  this, SLOT(UpdateLightAttenuation()));
  connect(ui->lightAttenuationB, SIGNAL(valueChanged(double)),  this, SLOT(UpdateLightAttenuation()));
  connect(ui->lightAttenuationC, SIGNAL(valueChanged(double)),  this, SLOT(UpdateLightAttenuation()));
  connect(ui->lightTypesList,    SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateLightType()));
  connect(ui->lightCompile,      SIGNAL(clicked()),             this, SLOT(LightCompile()));
  connect(ui->lightPriority,     SIGNAL(valueChanged(int)),     this, SLOT(UpdateLightPriority()));
  connect(ui->addLightTarget,    SIGNAL(clicked()),             this, SLOT(AddEnlightenedObject()));
  connect(ui->deleteLightTarget, SIGNAL(clicked()),             this, SLOT(DeleteEnlightenedObject()));
  connect(ui->showFrustum,       SIGNAL(toggled(bool)),         this, SLOT(LightShowFrustum(bool)));
  connect(ui->lightTargets,      SIGNAL(updatedPriority()),     this, SLOT(UpdateEnlightenedObject()));
  connect(ui->lightTargets,      SIGNAL(updatedPropagation()),  this, SLOT(UpdateEnlightenedObject()));

  // Light -> Shadow caster
  connect(ui->shadowFilmSize,    SIGNAL(valueChanged(int)),     this, SLOT(UpdateShadowCaster()));
  connect(ui->shadowNear,        SIGNAL(valueChanged(int)),     this, SLOT(UpdateShadowCaster()));
  connect(ui->shadowFar,         SIGNAL(valueChanged(int)),     this, SLOT(UpdateShadowCaster()));
  connect(ui->shadowBufferSizeX, SIGNAL(valueChanged(int)),     this, SLOT(UpdateShadowCaster()));
  connect(ui->shadowBufferSizeY, SIGNAL(valueChanged(int)),     this, SLOT(UpdateShadowCaster()));

  // Render
  connect(ui->selectModel,   SIGNAL(clicked()), this, SLOT(PickModel()));
  connect(ui->selectTexture, SIGNAL(clicked()), this, SLOT(PickTexture()));
  connect(ui->objectModel,   SIGNAL(textChanged(QString)), this, SLOT(UpdateRender()));
  connect(ui->objectTexture, SIGNAL(textChanged(QString)), this, SLOT(UpdateRender()));
  connect(ui->objectFocus,   SIGNAL(clicked()), this, SLOT(FocusCurrentObject()));
  connect(ui->useTexture,    SIGNAL(toggled(bool)), this, SLOT(UpdateRender()));
  connect(ui->useColor,      SIGNAL(toggled(bool)), this, SLOT(UpdateRender()));
  connect(ui->useOpacity,    SIGNAL(toggled(bool)), this, SLOT(UpdateRender()));
  connect(ui->colorRed,      SIGNAL(valueChanged(double)), SLOT(UpdateRender()));
  connect(ui->colorGreen,    SIGNAL(valueChanged(double)), SLOT(UpdateRender()));
  connect(ui->colorBlue,     SIGNAL(valueChanged(double)), SLOT(UpdateRender()));
  connect(ui->opacity,       SIGNAL(valueChanged(double)), SLOT(UpdateRender()));
  connect(ui->objectToggleVisibility, SIGNAL(clicked()), this, SLOT(ToogleCurrentObject()));

  // Waypoint
  connect(ui->setCurrentWaypoint, SIGNAL(clicked()), this, SLOT(SetCurrentWaypoint()));
  connect(ui->selectCurrentWaypoint, SIGNAL(clicked()), this, SLOT(SelectCurrentWaypoint()));

  // Behaviour
  connect(ui->objectTypeList,       SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateBehaviour()));
  connect(ui->character,            SIGNAL(textChanged(QString)),     this, SLOT(UpdateBehaviour()));
  connect(ui->dialog,               SIGNAL(textChanged(QString)),     this, SLOT(UpdateBehaviour()));
  connect(ui->script,               SIGNAL(textChanged(QString)),     this, SLOT(UpdateBehaviour()));
  connect(ui->doorLocked,           SIGNAL(toggled(bool)),            this, SLOT(UpdateBehaviour()));
  connect(ui->key,                  SIGNAL(textChanged(QString)),     this, SLOT(UpdateBehaviour()));
  connect(ui->interactionUse,       SIGNAL(toggled(bool)),            this, SLOT(UpdateBehaviour()));
  connect(ui->interactionUseSkill,  SIGNAL(toggled(bool)),            this, SLOT(UpdateBehaviour()));
  connect(ui->interactionUseSpell,  SIGNAL(toggled(bool)),            this, SLOT(UpdateBehaviour()));
  connect(ui->interactionUseObject, SIGNAL(toggled(bool)),            this, SLOT(UpdateBehaviour()));
  connect(ui->interactionLookAt,    SIGNAL(toggled(bool)),            this, SLOT(UpdateBehaviour()));
  connect(ui->interactionTalkTo,    SIGNAL(toggled(bool)),            this, SLOT(UpdateBehaviour()));
  connect(ui->selectCharacter,      SIGNAL(clicked()),                this, SLOT(SelectCharacter()));
  connect(ui->selectItem,           SIGNAL(clicked()),                this, SLOT(SelectItem()));
  connect(ui->selectKey,            SIGNAL(clicked()),                this, SLOT(SelectKey()));
  connect(ui->selectScript,         SIGNAL(clicked()),                this, SLOT(SelectScript()));
  connect(ui->selectDialog,         SIGNAL(clicked()),                this, SLOT(SelectDialog()));

  // Render Particles
  connect(ui->particleEffectName,   SIGNAL(textChanged(QString)), this, SLOT(UpdateParticleEffect()));
  connect(ui->showParticleEffect,   SIGNAL(clicked()),            this, SLOT(RestartParticleEffect()));
  connect(ui->selectParticleEffect, SIGNAL(clicked()),            this, SLOT(SelectParticleEffect()));

  ui->actionsButton->setMenu(&action_menu);
  action_menu.addAction("Copy",  this, SIGNAL(CopyRequested()),  QKeySequence::Copy);
  action_menu.addAction("Paste", this, SIGNAL(PasteRequested()), QKeySequence::Paste);
}
Esempio n. 9
0
int TaskForceClass::MoveUnit (CampaignTime time)
{
    GridIndex x = 0, y = 0;
    GridIndex nx = 0, ny = 0;
    GridIndex ox = 0, oy = 0;
    WayPoint w = NULL, ow = NULL;
    Objective o = NULL;
    int	moving = 1;
    CampaignHeading	h = 0;

    // RV - Biker
    // Naval units now have three modes:
    // (a) Sit still in harbor
    // (b) Do a 20 km track (repeating waypoints)
    // (c) Followy WPs

    GetLocation(&x,&y);

    w = ResetCurrentWP(this);

    FindNearestUnit(x, y, NULL);

    // Check for mode a
    o = FindNearestObjective(x, y, NULL, 1);

    // RV - Biker - If we are in port and have no WPs do nothing
    if (o && o->GetType() == TYPE_PORT && !w) {
        return TRUE;
    }

    // If not in port and no WPs... create a repeating path 20 km north and back
    if (!w)	{
        DisposeWayPoints();

        w = AddUnitWP(x, y, 0, 60,	TheCampaign.CurrentTime + (rand()%15), 0, 0);
        w->SetWPFlags(WPF_REPEAT);

        // This should prevent naval units to run into ground
        if (GetCover(x, y+20) == Water) {
            w = AddUnitWP(x, y+20, 0, 60, TheCampaign.CurrentTime + (15+(rand()%15))*CampaignMinutes, 0, 0);
        }
        else {
            w = AddUnitWP(x, y, 0, 60, TheCampaign.CurrentTime + 15*CampaignMinutes, 0, 0);
        }
        w->SetWPFlags(WPF_REPEAT);

        w = AddUnitWP(x, y, 0, 60, TheCampaign.CurrentTime + (30+(rand()%15))*CampaignMinutes, 0xffffffff, 0);
        w->SetWPFlags(WPF_REPEAT);

        SetCurrentWaypoint (1);
        w = GetCurrentUnitWP();
    }

    w->GetWPLocation(&nx, &ny);

    // RV - Biker - Wait for departure
    if (Camp_GetCurrentTime() < w->GetWPDepartureTime()) {
        SetUnitLastMove(Camp_GetCurrentTime());
        return 0;
    }

    // Move, if we're not at destination
    if (x!=nx || y!=ny)
    {
        if (w)
            ow = w->GetPrevWP();
        if (ow)
            ow->GetWPLocation(&ox, &oy);
        else
            GetLocation(&ox, &oy);

        while (moving) {
            h = DirectionTo(ox, oy, nx, ny, x, y);
            if (h > 7) {
                moving = 0;
                h = Here;
            }
            // This is kinda hacky - basically, limit change in direction to 45 deg per move
            if (h > last_direction) {
                if (h - last_direction < 5)
                    h = (last_direction+1) & 0x07;
                else
                    h = (last_direction+7) & 0x07;
            }

            else if (h < last_direction) {
                if (last_direction - h < 5)
                    h = (last_direction+7) & 0x07;
                else
                    h = (last_direction+1) & 0x07;
            }

            //this moves the unit
            if (ChangeUnitLocation(h) > 0) {
                last_direction = h;
            }
            else {
                moving = 0;
            }

            // Now do combat
            if (GetCombatTime() > CombatTime()) {
                DoCombat();
            }
        }
    }
    return 0;
}
Esempio n. 10
0
entity *CACBot::SearchForFlags(bool bUseWPs, float flRange, float flMaxHeight)
{
    /*
        Flags are scored on the following:
        - Distance
    */
    float flDist;
    entity *pNewTargetFlag = NULL;
    waypoint_s *pWptNearBot = NULL, *pBestWpt = NULL;
    short sScore, sHighestScore = 0;
    vec vNewGoal = g_vecZero;

    if ((WaypointClass.m_iWaypointCount >= 1) && bUseWPs)
        pWptNearBot = GetNearestWaypoint(200.0f);

#ifdef WP_FLOOD
    if (!pWptNearBot && bUseWPs)
        pWptNearBot = GetNearestFloodWP(64.0f);
#endif

    loopv(ents)
    {
        sScore = 0;
        entity &e = ents[i];
        if(!CanTakeFlag(e)) continue;
        //vec o = g_vecZero;
        vec o = vec(e.x, e.y, S(e.x, e.y)->floor + PLAYERHEIGHT + PLAYERABOVEEYE);
        if(!m_secure(gamemode) && e.attr2 >= 0 && e.attr2 < 2)
        {
            flaginfo &f = flaginfos[e.attr2];
            // flaginfo &of = flaginfos[team_opposite(i)];
            if(f.state == CTFF_DROPPED)
            {
                o = f.pos;
                o.z += PLAYERHEIGHT + PLAYERABOVEEYE;
            }
        }
        if(OUTBORD((int)o.x, (int)o.y)) continue;
        flDist = GetDistance(o);
        if (flDist > flRange) continue;

        // Score on distance
        float ff = flDist;
        if (ff > 100.0f) ff = 100.0f;
        sScore += ((100 - short(ff)) / 2);

        waypoint_s *pWptNearEnt = NULL;
        // If this flag entity isn't visible check if there is a nearby waypoint
        if (!IsReachable(o, flMaxHeight))//(!IsVisible(o))
        {
            if (!pWptNearBot) continue;

#ifdef WP_FLOOD
            if (pWptNearBot->pNode->iFlags & W_FL_FLOOD)
                pWptNearEnt = GetNearestFloodWP(o, 100.0f);
            else
#endif
                pWptNearEnt = GetNearestWaypoint(o, 200.f);

            if (!pWptNearEnt) continue;
        }

        // Score on visibility
        if (pWptNearEnt == NULL) // Ent is visible
            sScore += 6;
        else
            sScore += 3;

        if(sScore > sHighestScore)
        {
            if (pWptNearEnt) pBestWpt = pWptNearEnt;
            else pBestWpt = NULL; // best flag doesn't need any waypoints

            vNewGoal = o;
            pNewTargetFlag = &e;
        }
    }

    if (pNewTargetFlag)
    {
        // Need waypoints to reach it?
        if (pBestWpt)
        {
            ResetWaypointVars();
            SetCurrentWaypoint(pWptNearBot);
            SetCurrentGoalWaypoint(pBestWpt);
        }
        m_vGoal = vNewGoal;
    }

    return pNewTargetFlag;
}
Esempio n. 11
0
entity *CACBot::SearchForEnts(bool bUseWPs, float flRange, float flMaxHeight)
{
    /* Entities are scored on the following things:
        - Visibility
        - For ammo: Need(ie has this bot much of this type or not)
        - distance
    */

    float flDist;
    entity *pNewTargetEnt = NULL;
    waypoint_s *pWptNearBot = NULL, *pBestWpt = NULL;
    short sScore, sHighestScore = 0;

    if ((WaypointClass.m_iWaypointCount >= 1) && bUseWPs)
        pWptNearBot = GetNearestWaypoint(15.0f);

#ifdef WP_FLOOD
    if (!pWptNearBot && bUseWPs)
        pWptNearBot = GetNearestFloodWP(5.0f);
#endif

    loopv(ents)
    {
        sScore = 0;
        entity &e = ents[i];
        vec o(e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight);

        if (!ents[i].spawned) continue;
        if (OUTBORD(e.x, e.y)) continue;

        bool bInteresting = false;
        short sAmmo = 0, sMaxAmmo = 0;

        switch(e.type)
        {
            case I_CLIPS:
                sMaxAmmo = ammostats[m_pMyEnt->secondary].max;
                bInteresting = (m_pMyEnt->ammo[m_pMyEnt->secondary]<sMaxAmmo);
                sAmmo = m_pMyEnt->ammo[m_pMyEnt->secondary];
                break;
            case I_AMMO:
                sMaxAmmo = ammostats[m_pMyEnt->primary].max;
                bInteresting = (m_pMyEnt->ammo[m_pMyEnt->primary]<sMaxAmmo);
                sAmmo = m_pMyEnt->ammo[m_pMyEnt->primary];
                break;
            case I_GRENADE:
                sMaxAmmo = ammostats[GUN_GRENADE].max;
                bInteresting = (m_pMyEnt->mag[GUN_GRENADE]<sMaxAmmo);
                sAmmo = -1;
                break;
            case I_HEALTH:
                sMaxAmmo = MAXHEALTH;
                bInteresting = (m_pMyEnt->health < sMaxAmmo);
                sAmmo = m_pMyEnt->health;
                break;
            case I_HELMET:
            case I_ARMOUR:
               sMaxAmmo = MAXARMOUR;
               bInteresting = (m_pMyEnt->armour < sMaxAmmo);
               sAmmo = m_pMyEnt->armour;
               break;
            case I_AKIMBO:
               bInteresting = !m_pMyEnt->akimbo;
               sAmmo = -1;
               break;
        };

        if (!bInteresting)
            continue; // Not an interesting item, skip

        // Score on ammo and need
        // Akimbo & nade
        if (sAmmo == -1)
        {
            sScore += 75; // Bonus
        }
        else
        {
            // Calculate current percentage of max ammo
            float percent = ((float)sAmmo / (float)sMaxAmmo) * 100.0f;
            if (percent > 100.0f) percent = 100.0f;
            sScore += ((100 - short(percent))/2);
        }

        flDist = GetDistance(o);

        if (flDist > flRange) continue;

        // Score on distance
        float f = flDist;
        if (f > 100.0f) f = 100.0f;
        sScore += ((100 - short(f)) / 2);

        waypoint_s *pWptNearEnt = NULL;
        // If this entity isn't visible check if there is a nearby waypoint
        if (!IsReachable(o, flMaxHeight))//(!IsVisible(o))
        {
            if (!pWptNearBot) continue;

#ifdef WP_FLOOD
            if (pWptNearBot->pNode->iFlags & W_FL_FLOOD)
                pWptNearEnt = GetNearestFloodWP(o, 8.0f);
            else
#endif
                pWptNearEnt = GetNearestWaypoint(o, 15.0f);

            if (!pWptNearEnt) continue;
        }

        // Score on visibility
        if (pWptNearEnt == NULL) // Ent is visible
            sScore += 30;
        else
            sScore += 15;

        if (sScore > sHighestScore)
        {
            // Found a valid wp near the bot and the ent,so...lets store it :)
            if (pWptNearEnt)
                pBestWpt = pWptNearEnt;
            else
                pBestWpt = NULL; // Best ent so far doesn't need any waypoints

            sHighestScore = sScore;
            pNewTargetEnt = &ents[i];
        }
    }

    if (pNewTargetEnt)
    {
        // Need waypoints to reach it?
        if (pBestWpt)
        {
            ResetWaypointVars();
            SetCurrentWaypoint(pWptNearBot);
            SetCurrentGoalWaypoint(pBestWpt);
        }

        m_vGoal.x = pNewTargetEnt->x;
        m_vGoal.y = pNewTargetEnt->y;
        m_vGoal.z = S(pNewTargetEnt->x, pNewTargetEnt->y)->floor+player1->eyeheight;
    }

    return pNewTargetEnt;
}