Пример #1
0
        void DoNormalAttack(uint32 diff)
        {
            opponent = me->GetVictim();
            if (opponent)
            {
                if (!IsCasting())
                    StartAttack(opponent, true);
            }
            else
                return;
            if (MoveBehind(*opponent))
                wait = 5;

            //float dist = me->GetExactDist(opponent);
            float meleedist = me->GetDistance(opponent);

            //TORMENT
            if (IsSpellReady(TORMENT_1, diff, false) && meleedist < 5 && !IsTank(opponent->GetVictim()))
            {
                temptimer = GC_Timer;
                if (doCast(opponent, GetSpell(TORMENT_1)))
                {
                    GC_Timer = temptimer;
                    return;
                }
            }
        }
Пример #2
0
void Player::OnKeyDown(const CL_InputEvent &key, const CL_InputState &state)
{
	if (m_flags[eDead]) {
		//TODO: I was a bit lazy here, maybe introduce respawn key as a keybind?
		if (key.id == CL_KEY_F1) {
			Respawn();
		}
		return;
	}

	//TODO: can this be turned into a switch-case without breaking logic?

	if (key.id == m_moveLeftKey) {
		m_moveLeftKeyPressed = true;
		StartMoving(eLeft);
	} 

	if (key.id == m_moveRightKey) {
		m_moveRightKeyPressed = true;
		StartMoving(eRight);
	}

	if (key.id == m_jumpKey && !m_jumpKeyPressed) {
		m_jumpKeyPressed = true;
		StartJump();
	}

	if (key.id == m_attackKey && !m_attackKeyPressed) {
		m_attackKeyPressed = true;
		StartAttack();
	}
}
Пример #3
0
        void DoNormalAttack(uint32 diff)
        {
            opponent = me->GetVictim();
            if (opponent)
            {
                if (!IsCasting())
                    StartAttack(opponent, true);
            }
            else
                return;
            if (MoveBehind(*opponent))
                wait = 5;

            //float dist = me->GetExactDist(opponent);
            float meleedist = me->GetDistance(opponent);

            //TORMENT
            if (TORMENT && Torment_cd <= diff && meleedist < 5 && (!tank || tank == me || opponent->GetVictim() == m_creatureOwner))
            {
                temptimer = GC_Timer;
                if (doCast(opponent, TORMENT))
                {
                    Torment_cd = 5000;
                    GC_Timer = temptimer;
                    return;
                }
            }
        }
Пример #4
0
void NPC::ShootArrow()
{
	if (!m_flags[eAttacking])
	{
		//TODO: this isn't properly cleaned up.
		MovingObject* arrow = new MovingObject(m_graphicContext, *m_resourceManager, m_position.x, m_position.y, "Arrow");
		arrow->ConnectSlots(*m_drawSignal, *m_updateSignal);
		arrow->SetEnvList(m_environment);
		double launchAngle = Utility::CalculateTrajectory(arrow->GetPosition(), m_target->GetPosition(), arrow->GetSpeed(eCompositeSpeed), true);
		arrow->SetSpeed(eXSpeed, arrow->GetSpeed(eCompositeSpeed) * sin(launchAngle));
		arrow->SetSpeed(eYSpeed, arrow->GetSpeed(eCompositeSpeed) * cos(launchAngle));

		StartAttack();
		arrow->StartMoving(m_direction);
	}
}
Пример #5
0
void NPC::TakeAction(BasicAction action, int timeElapsedMs)
{
	//TODO: terrible code, consider using references
	switch (action)	{
	case eAttack: {
		StopMoving();
		StartAttack(); //TODO: might need to override
		break;
	}	
	case eMove: { //compiler mistook this for the Move() method..
		// reset speed to normal
		if (m_flags[eAffectedByGravity] && !m_flags[eJumping] && !m_flags[eFalling]) {
			m_speeds[eXSpeed] = m_speedX;
			m_speeds[eYSpeed] = m_speedY;
		}
		StartMoving(GetDirection());
		break;
	}	
	case eFlee: {
		// reset speed to normal
		if (m_flags[eAffectedByGravity] && !m_flags[eJumping] && !m_flags[eFalling]) {
			m_speeds[eXSpeed] = m_speedX;
			m_speeds[eYSpeed] = m_speedY;
		}
		//avoid colliding with the character
		//TODO: WHAT? This makes no sense (even before refactor)
		StartMoving(m_direction == eLeft ? eRight : eLeft);
		break;
	}	
	case eJump: {
		StartJump();
		break;
	}
	case eShoot: {
		Shoot(m_attackType);
		break;
	}
	default: {
		StopMoving();
		if (!m_flags[eAffectedByGravity]) {
			m_speeds[eXSpeed] = 0;
			m_speeds[eYSpeed] = 0;
		}
		break;
	}
	}
}
Пример #6
0
//TODO: fix shoot direciton and, if possible amount of objects created
void NPC::ShootMissile()
{
	if (!m_flags[eAttacking])
	{
		//TODO: this isn't properly cleaned up. Also need to add it to Level's object lists
		//All in all we need a better way to create projectiles
		MovingObject* missile = new MovingObject(m_graphicContext, *m_resourceManager, m_position.x, m_position.y, "Missile");
		missile->ConnectSlots(*m_drawSignal, *m_updateSignal);
		missile->SetEnvList(m_environment);
		missile->SetDirection(m_direction);

		if (missile->GetDirection() == eLeft) {
			missile->SetSpeed(eXSpeed, -missile->GetSpeed(eXSpeed));
		}
		StartAttack();
		missile->StartMoving(m_direction);
		m_timeSinceLastAttack = CL_System::get_time();
	}
}
Пример #7
0
void RPG_Action_RangedAttack::Tick(float const deltaTime)
{
  RPG_Action_AttackBase::Tick(deltaTime);

  if(m_attacking)
  {
    // RangedAttacking was set to true when the action was initiated. Is reset to false by Behavior when the attack anim finishes.
    vHavokBehaviorComponent *const behaviorComponent = m_characterOwner->GetBehaviorComponent();
    VVERIFY_OR_RET(behaviorComponent);

    VASSERT(!m_behaviorTriggerVarName.IsEmpty());
    if (!RPG_VisionHavokBehaviorHelper::BehaviorGetVarNamed<bool>(*behaviorComponent, m_behaviorTriggerVarName.AsChar()))
    {
      if (m_flags == 1)
      {
        if(m_updatedInteraction)
        {
          m_updatedInteraction = false;
          if(!m_updatedInteractionEntity && m_interactionEntity)
          {
            // Do not lose the player's intended target
            ValidateInteractionEntity();
            if(!m_interactionEntity->Components().GetComponentOfType(V_RUNTIME_CLASS(RPG_AttackableComponent)))
            {
              m_interactionEntity = NULL;
            }
            else
            {
              if(m_interactionEntity->GetPosition().getDistanceToSquared(m_updatedInteractionPosition) > s_retargetingRadius * s_retargetingRadius)
              {
                m_interactionEntity = NULL;
              }
            }
          }
          else
          {
            m_interactionEntity = m_updatedInteractionEntity;
            ValidateInteractionEntity();
          }
          m_interactionPosition = m_updatedInteractionPosition;
        }
        m_startTime = Vision::GetTimer()->GetTime();
        StartAttack();
      }
      else
      {
        // if we've gotten to the end and haven't fired the projectile, fire it now
        if (!m_hasFired)
        {
          VString msg;
          msg.Format("RPG_Action_RangedAttack never received expected %s event from Behavior.", m_behaviorFireEventName.AsChar());
          Vision::Error.Warning(msg.AsChar());
          //VASSERT_MSG(false, msg.AsChar());
          FireAttack();
        }
        End();
      }
    }
    else
    {
      // we're currently attacking
      hkvVec3 const targetPosition = m_interactionEntity ? m_interactionEntity->GetPosition() : m_interactionPosition;
      FaceTargetPoint(targetPosition);

#ifdef _DEBUG
      if (m_debugDisplayInfo)
      {
        Vision::Game.DrawSingleLine(m_characterOwner->GetPosition(), targetPosition, VColorRef(255, 0, 255));
      }
#endif
    }
  }
  else
  {
    StartAttack();
  }
}
Пример #8
0
            void EnterCombat(Unit* /*who*/) override
            {
                _EnterCombat();

                StartAttack();
            }
Пример #9
0
        void DoNormalAttack(uint32 diff)
        {
            opponent = me->GetVictim();
            if (opponent)
            {
                if (!IsCasting())
                    StartAttack(opponent);
            }
            else
                return;

            AttackerSet m_attackers = master->getAttackers();
            AttackerSet b_attackers = me->getAttackers();

            Unit* u = me->SelectNearestTarget(20);
            //ICE_BARRIER
            if (ICE_BARRIER && Ice_Barrier_cd <= diff && u && u->GetVictim() == me &&
                u->GetDistance(me) < 8 && !me->HasAura(ICE_BARRIER))
            {
                if (me->IsNonMeleeSpellCast(true))
                    me->InterruptNonMeleeSpells(true);
                if (doCast(me, ICE_BARRIER))
                {
                    Ice_Barrier_cd = 25000;
                    GC_Timer = 800;
                    return;
                }
            }
            if ((!ICE_BARRIER || Ice_Barrier_cd > diff) &&
                BLINK && Blink_cd < 3000 && u && u->GetVictim() == me &&
                u->GetDistance(me) < 6 && !me->HasAura(ICE_BARRIER))
            {
                if (me->IsNonMeleeSpellCast(true))
                    me->InterruptNonMeleeSpells(true);
                if (doCast(me, BLINK))
                {
                    Blink_cd = 13000;
                    GC_Timer = 800;
                    return;
                }
            }

            if (me->HasAura(ICEBLOCK))
                if (((GetManaPCT(me) > 45 && GetHealthPCT(me) > 80) || b_attackers.empty()) && Iceblock_cd <= 57000 && tank)
                    me->RemoveAurasDueToSpell(ICEBLOCK);
            //ICEBLOCK
            if (ICEBLOCK && Rand() < 50 && !b_attackers.empty() && tank && Iceblock_cd <= diff &&
                (GetManaPCT(me) < 15 || GetHealthPCT(me) < 45 || b_attackers.size() > 4) &&
                !me->HasAura(ICEBLOCK))
            {
                if (me->IsNonMeleeSpellCast(true))
                    me->InterruptNonMeleeSpells(true);
                if (doCast(me, ICEBLOCK))
                {
                    Iceblock_cd = 60000;
                    Nova_cd = 0; //Glyph of Iceblock
                    return;
                }
            }

            if (IsCasting()) return;

            float dist = me->GetExactDist(opponent);

            BOLT = (CCed(opponent, true) || !FROSTBOLT) ? FIREBALL : FROSTBOLT;
            NOVA = BOLT == FROSTBOLT && BLASTWAVE && dist > 5 ? BLASTWAVE : FROSTNOVA ? FROSTNOVA : 0;

            ////Combustion doesn't work properly on 434 (14.08.13)
            //if (COMBUSTION && Combustion_cd <= diff && Rand() < 15 && dist < 40)
            //{
            //    if (opponent->HasAuraTypeWithCaster(SPELL_AURA_PERIODIC_DAMAGE, me->GetGUID()))
            //    {
            //        temptimer = GC_Timer;
            //        if (doCast(me, COMBUSTION))
            //        {
            //            Combustion_cd = 60000;
            //            Nova_cd = 0; FireBlast_cd = 0; DragonBreath_cd = 0;
            //        }
            //        GC_Timer = temptimer;
            //    }
            //}
            //DAMAGE
            //PYROBLAST
            if (PYROBLAST && Pyroblast_cd <= diff && GC_Timer <= diff && Rand() < 95 &&
                (b_attackers.size() < 2 || (*b_attackers.begin()) == opponent) &&
                dist < 40 && opponent->IsPolymorphed() &&
                doCast(opponent, PYROBLAST))
            {
                Pyroblast_cd = 7500;
                //debug
                DragonBreath_cd = std::max<uint32>(DragonBreath_cd, 450);
                Nova_cd = std::max<uint32>(Nova_cd, 450);
                return;
            }
            //nova //TODO: SEPARATE
            u = me->SelectNearestTarget(6.3f);
            if (NOVA && Nova_cd <= diff && u && Rand() < 75 && !CCed(u, true) && IsInBotParty(u->GetVictim()))
            {
                if (doCast(me, NOVA))
                {
                    Nova_cd = 15000;
                    GetInPosition(true);
                    return;
                }
            }
            //living bomb
            if (LIVINGBOMB && Living_Bomb_cd <= diff && GC_Timer <= diff && Rand() < 45 && dist < 40 &&
                opponent->GetHealth() > me->GetHealth()/2 &&
                !opponent->HasAura(LIVINGBOMB, me->GetGUID()) &&
                doCast(opponent, LIVINGBOMB))
            {
                Living_Bomb_cd = 6000;
                GC_Timer = 500;
                return;
            }
            //cone of cold
            if (CONEOFCOLD && ConeofCold_cd <= diff && GC_Timer <= diff && Rand() < 50 && dist < 7 &&
                me->HasInArc(M_PI*0.75f, opponent) &&
                doCast(opponent, CONEOFCOLD))
            {
                ConeofCold_cd = 8000;
                GC_Timer = 500;
                GetInPosition(true);
                return;
            }
            //dragon's breath
            if (DRAGONBREATH && DragonBreath_cd <= diff && GC_Timer <= diff && !CCed(opponent, true) &&
                ((me->HasInArc(M_PI*0.75f, opponent) && dist < 7) ||
                (u && u != opponent && me->HasInArc(M_PI*0.75f, u) && IsInBotParty(u->GetVictim()))) &&
                doCast(/*opponent*/me, DRAGONBREATH))
            {
                DragonBreath_cd = 15000;
                GC_Timer = 800;
                return;
            }
            /*//blast wave //TODO Separate again
            u = me->SelectNearestTarget(8);
            if (BLASTWAVE != 0 && u && isTimerReady(BlastWave_cd) &&
                !HasAuraName(u, FROSTNOVA) && !HasAuraName(u, DRAGONBREATH) &&
                doCast(me, BLASTWAVE))
            {
                BlastWave_cd = BLASTWAVE_CD;
                GC_Timer = 800;
            }*/
            //fire blast
            if (FIREBLAST && FireBlast_cd <= diff && GC_Timer <= diff && dist < 40)
            {
                if (Rand() < 20 + 80*(!opponent->isFrozen() && !opponent->HasAuraType(SPELL_AURA_MOD_STUN) && me->HasAura(IMPACT_BUFF)))
                {
                    if (doCast(opponent, FIREBLAST))
                    {

                        FireBlast_cd = 6000;
                        GC_Timer = 500;
                        return;
                    }
                }
            }
            //flamestrike - use Improved Flamestrike for instant cast
            if (FLAMESTRIKE && GC_Timer <= diff && me->getLevel() >= 50 && Rand() < 25)
            {
                Unit* FStarget = FindAOETarget(40, true, false);
                if (FStarget && doCast(FStarget, FLAMESTRIKE, true))
                    return;
            }
            //blizzard
            if (BLIZZARD && Blizzard_cd <= diff && !me->isMoving() && Rand() < 40)
            {
                Unit* blizztarget = FindAOETarget(35, true);
                if (blizztarget && doCast(blizztarget, BLIZZARD))
                {
                    Blizzard_cd = 5000;
                    return;
                }
                Blizzard_cd = 1500; //fail
            }
            //Frost of Fire Bolt
            if (BOLT && Bolt_cd <= diff && Rand() < 75 && dist < 35 &&
                doCast(opponent, BOLT))
            {
                Bolt_cd = uint32(float(sSpellMgr->GetSpellInfo(BOLT)->CalcCastTime()/100) * me->GetFloatValue(UNIT_MOD_CAST_SPEED) + 200);
                //debug
                DragonBreath_cd = std::max<uint32>(DragonBreath_cd, 450);
                Nova_cd = std::max<uint32>(Nova_cd, 450);
                return;
            }
            ////Arcane Missiles
            //if (Rand() < 15 && GC_Timer <= diff && !me->isMoving() && dist < 40 &&
            //    doCast(opponent, ARCANEMISSILES))
            //    return;
        }
Пример #10
0
        void DoNormalAttack(uint32 diff)
        {
            opponent = me->GetVictim();
            if (opponent)
            {
                if (!IsCasting())
                    StartAttack(opponent);
            }
            else
                return;

            //TODO: add more damage spells

            if (fear_cd <= diff && GC_Timer <= diff)
            { CheckFear(); fear_cd = 2000; }

            if (RAIN_OF_FIRE && Rain_of_fire_cd <= diff && GC_Timer <= diff && !me->isMoving() && Rand() < 25)
            {
                Unit* blizztarget = FindAOETarget(35, true);
                if (blizztarget && doCast(blizztarget, RAIN_OF_FIRE))
                {
                    Rain_of_fire_cd = 5000;
                    return;
                }
                Rain_of_fire_cd = 2000;//fail
            }

            float dist = me->GetExactDist(opponent);

            if (CURSE_OF_THE_ELEMENTS && GC_Timer <= diff && dist < 40 && Rand() < 15 &&
                !HasAuraName(opponent, CURSE_OF_THE_ELEMENTS) &&
                doCast(opponent, CURSE_OF_THE_ELEMENTS))
            {
                GC_Timer = 800;
                return;
            }

            if (CORRUPTION && GC_Timer <= diff && dist < 40 && Rand() < 25 &&
                !opponent->HasAura(CORRUPTION, me->GetGUID()) &&
                doCast(opponent, CORRUPTION))
                return;

            if (HAUNT && Haunt_cd <= diff && GC_Timer <= diff && dist < 40 && Rand() < 25 &&
                !opponent->HasAura(HAUNT, me->GetGUID()) &&
                doCast(opponent, HAUNT))
            {
                Haunt_cd = 8000;
                return;
            }

            if (GC_Timer <= diff && dist < 40 && Rand() < 15 && !Afflicted(opponent))
            {
                if (IMMOLATE && (!CONFLAGRATE || conflagarate_cd <= 8000) && doCast(opponent, IMMOLATE))
                    return;
                else if (UNSTABLE_AFFLICTION && doCast(opponent, UNSTABLE_AFFLICTION))
                    return;
            }

            if (CONFLAGRATE && conflagarate_cd <= diff && GC_Timer <= diff && dist < 40 && Rand() < 35 &&
                HasAuraName(opponent, IMMOLATE) &&
                doCast(opponent, CONFLAGRATE))
            {
                conflagarate_cd = 8000;
                return;
            }

            if (CHAOS_BOLT && chaos_bolt_cd <= diff && GC_Timer <= diff && dist < 40 && Rand() < 50 &&
                doCast(opponent, CHAOS_BOLT))
            {
                chaos_bolt_cd = me->getLevel() < 80 ? 10000 : 8000;
                return;
            }

            if (SHADOW_BOLT && GC_Timer <= diff && dist < 40 &&
                doCast(opponent, SHADOW_BOLT))
                return;
        }
Пример #11
0
void noFighting::HandleEvent(const unsigned int id)
{
    // Normales Ablaufevent?
    if(id == 0)
    {
        switch(turn)
        {
        case 2:
        {
            // Der Kampf hat gerade begonnen

            // "Auslosen", wer als erstes dran ist mit Angreifen
            turn = static_cast<unsigned char>(RANDOM.Rand(__FILE__, __LINE__, GetObjId(), 2));
            // anfangen anzugreifen
            StartAttack();
        } return;
        case 0:
        case 1:
        {
            // Sounds löschen von der letzten Kampfphase
            SOUNDMANAGER.WorkingFinished(this);

            // Wurde der eine getroffen?
            if(defending_animation == 3)
            {
                if(--soldiers[1 - turn]->hitpoints == 0)
                {
                    // Besitzer merken für die Sichtbarkeiten am Ende dann
                    player_won = soldiers[turn]->GetPlayer();
                    // Soldat Bescheid sagen, dass er stirbt
                    soldiers[1 - turn]->LostFighting();
                    // Anderen Soldaten auf die Karte wieder setzen, Bescheid sagen, er kann wieder loslaufen
                    gwg->AddFigure(soldiers[turn], soldiers[turn]->GetPos());
                    soldiers[turn]->WonFighting();
                    soldiers[turn] = NULL;
                    // Hitpoints sind 0 --> Soldat ist tot, Kampf beendet, turn = 3+welche Soldat stirbt
                    turn = 3 + (1 - turn);
                    // Event zum Sterben des einen Soldaten anmelden
                    current_ev = GetEvMgr().AddEvent(this, 30);
                    // Umstehenden Figuren Bescheid Bescheid sagen
                    gwg->RoadNodeAvailable(soldiers[turn - 3]->GetPos());

                    // In die Statistik eintragen
                    gwg->GetPlayer(player_won).ChangeStatisticValue(STAT_VANQUISHED, 1);
                    return;
                }
            }

            turn = 1 - turn;
            StartAttack();
        } return;
        case 3:
        case 4:
        {
            unsigned player_lost = turn - 3;
            MapPoint pt = soldiers[player_lost]->GetPos();

            // Sounds löschen vom Sterben
            SOUNDMANAGER.WorkingFinished(this);

            // Kampf ist endgültig beendet
            GetEvMgr().AddToKillList(this);
            gwg->RemoveFigure(this, pt);

            // Wenn da nix war bzw. nur ein Verzierungsobjekt, kommt nun ein Skelett hin
            NodalObjectType noType = gwg->GetNO(pt)->GetType();
            if(noType == NOP_NOTHING || noType == NOP_ENVIRONMENT)
            {
                gwg->DestroyNO(pt, false);
                gwg->SetNO(pt, new noSkeleton(pt));
            }

            // Sichtradius ausblenden am Ende des Kampfes, an jeweiligen Soldaten dann übergeben, welcher überlebt hat
            gwg->RecalcVisibilitiesAroundPoint(pt, VISUALRANGE_SOLDIER, soldiers[player_lost]->GetPlayer(), NULL);
            gwg->RecalcVisibilitiesAroundPoint(pt, VISUALRANGE_SOLDIER, player_won, NULL);

            // Soldaten endgültig umbringen
            gwg->GetPlayer(soldiers[player_lost]->GetPlayer()).DecreaseInventoryJob(soldiers[player_lost]->GetJobType(), 1);
            soldiers[player_lost]->Destroy();
            deletePtr(soldiers[player_lost]);

        } break;
        }
    } else
        RTTR_Assert(false);
}
Пример #12
0
        void DoNormalAttack(uint32 diff)
        {
            opponent = me->GetVictim();
            if (opponent)
            {
                if (!IsCasting())
                    StartAttack(opponent);
            }
            else
                return;

            //TODO: add more damage spells

            if (feartimer <= diff && GC_Timer <= diff)
            { CheckFear(); feartimer = 2000; }

            if (IsSpellReady(RAIN_OF_FIRE_1, diff) && !me->isMoving() && HasRole(BOT_ROLE_DPS) && Rand() < 25)
            {
                Unit* blizztarget = FindAOETarget(30, true);
                if (blizztarget && doCast(blizztarget, GetSpell(RAIN_OF_FIRE_1)))
                    return;
                SetSpellCooldown(RAIN_OF_FIRE_1, 2000);//fail
            }

            float dist = me->GetExactDist(opponent);

            if (IsSpellReady(CURSE_OF_THE_ELEMENTS_1, diff) && dist < 30 && Rand() < 15 &&
                !HasAuraName(opponent, CURSE_OF_THE_ELEMENTS_1) &&
                doCast(opponent, GetSpell(CURSE_OF_THE_ELEMENTS_1)))
            {
                GC_Timer = 800;
                return;
            }

            if (IsSpellReady(CORRUPTION_1, diff) && HasRole(BOT_ROLE_DPS) && dist < 30 && Rand() < 25 &&
                !opponent->HasAura(GetSpell(CORRUPTION_1), me->GetGUID()) &&
                doCast(opponent, GetSpell(CORRUPTION_1)))
                return;

            if (IsSpellReady(HAUNT_1, diff) && HasRole(BOT_ROLE_DPS) && dist < 30 && Rand() < 25 &&
                !opponent->HasAura(GetSpell(HAUNT_1), me->GetGUID()) &&
                doCast(opponent, GetSpell(HAUNT_1)))
                return;

            if (GC_Timer <= diff && HasRole(BOT_ROLE_DPS) && dist < 30 && Rand() < 15 && !Afflicted(opponent))
            {
                if (GetSpellCooldown(CONFLAGRATE_1) <= 8000 && doCast(opponent, GetSpell(IMMOLATE_1)))
                    return;
                else if (doCast(opponent, GetSpell(UNSTABLE_AFFLICTION_1)))
                    return;
            }

            if (IsSpellReady(CONFLAGRATE_1, diff) && HasRole(BOT_ROLE_DPS) && dist < 30 && Rand() < 35 &&
                HasAuraName(opponent, IMMOLATE_1) &&
                doCast(opponent, GetSpell(CONFLAGRATE_1)))
                return;

            if (IsSpellReady(CHAOS_BOLT_1, diff) && HasRole(BOT_ROLE_DPS) && dist < 30 && Rand() < 50 &&
                doCast(opponent, GetSpell(CHAOS_BOLT_1)))
                return;

            if (IsSpellReady(SHADOW_BOLT_1, diff) && HasRole(BOT_ROLE_DPS) && dist < 30 &&
                doCast(opponent, GetSpell(SHADOW_BOLT_1)))
                return;
        }
Пример #13
0
        void DoNormalAttack(uint32 diff)
        {
            opponent = me->GetVictim();
            if (opponent)
            {
                if (!IsCasting())
                    StartAttack(opponent);
            }
            else
                return;
            AttackerSet m_attackers = master->getAttackers();
            AttackerSet b_attackers = me->getAttackers();

            Unit* u = me->SelectNearestTarget(20);
            //ICE_BARRIER
            if (ICE_BARRIER && Ice_Barrier_cd <= diff && u && u->GetVictim() == me && 
                u->GetDistance(me) < 8 && !me->HasAura(ICE_BARRIER))
            {
                if (me->IsNonMeleeSpellCasted(true))
                    me->InterruptNonMeleeSpells(true);
                if (doCast(me, ICE_BARRIER))
                {
                    Ice_Barrier_cd = 41000 - me->getLevel()*200;//down to 25 sec on 80
                    GC_Timer = 800;
                    return;
                }
            }
            if ((!ICE_BARRIER || Ice_Barrier_cd > diff) && 
                BLINK && Blink_cd < 3000 && u && u->GetVictim() == me && 
                !me->HasAura(ICE_BARRIER) && u->GetDistance(me) < 6)
            {
                if (me->IsNonMeleeSpellCasted(true))
                    me->InterruptNonMeleeSpells(true);
                if (doCast(me, BLINK))
                {
                    Blink_cd = 15000 - me->getLevel()/4 * 100;
                    GC_Timer = 800;
                    return;
                }
            }

            if (me->HasAura(ICEBLOCK))
                if (((GetManaPCT(me) > 45 && GetHealthPCT(me) > 80) || b_attackers.empty()) && Iceblock_cd <= 57000 && tank)
                    me->RemoveAurasDueToSpell(ICEBLOCK);
            //ICEBLOCK
            if (ICEBLOCK && Rand() < 50 && !b_attackers.empty() && tank && Iceblock_cd <= diff && 
                (GetManaPCT(me) < 15 || GetHealthPCT(me) < 45 || b_attackers.size() > 4) && 
                !me->HasAura(ICEBLOCK))
            {
                if (me->IsNonMeleeSpellCasted(true))
                    me->InterruptNonMeleeSpells(true);
                if (doCast(me, ICEBLOCK))
                {
                    Iceblock_cd = 60000;
                    return;
                }
            }

            if (IsCasting()) return;

            BOLT = (CCed(opponent, true) || (opponent->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED) && me->HasAura(COMBUSTION))) ? FIREBALL : FROSTBOLT;
            NOVA = BOLT == FIREBALL && BLASTWAVE ? BLASTWAVE : FROSTNOVA ? FROSTNOVA : 0;

            float dist = me->GetExactDist(opponent);
            if (dist > 30)
                return;

            if (COMBUSTION && Rand() < 15 && 
                (opponent->GetMaxHealth() > master->GetMaxHealth()*10 || 
                m_attackers.size() > 1 || b_attackers.size() > 2))
            {
                if (!HasAuraName(me, "Combustion") && Combustion_cd <= diff)
                {
                    temptimer = GC_Timer;
                    if (doCast(me, COMBUSTION))
                    {
                        Combustion_cd = 60000;
                        //Reset timers for fun
                        Nova_cd = 0; FireBlast_cd = 0; DragonBreath_cd = 0;
                    }
                    GC_Timer = temptimer;
                }
            }
            //DAMAGE
            //PYROBLAST
            if (PYROBLAST && Rand() < 75 && Pyroblast_cd <= diff && GC_Timer <= diff && 
                b_attackers.size() < 2 && dist < 30 && opponent->IsPolymorphed() && 
                doCast(opponent, PYROBLAST))
                Pyroblast_cd = 50;
            //nova //TODO: SEPARATE
            u = me->SelectNearestTarget(7);
            if (u && NOVA && Nova_cd <= diff && !CCed(u, true) && IsInBotParty(u->GetVictim()))
            {
                Unit* tar = u->GetVictim();
                if (tar && IsInBotParty(tar) && doCast(me, NOVA))
                {
                    Nova_cd = 15000;
                    return;
                }
            }
            //living bomb
            if (LIVINGBOMB && Rand() < 25 && Living_Bomb_cd <= diff && GC_Timer <= diff && 
                dist < 30 && opponent->GetHealth() > me->GetHealth()/2 && 
                !opponent->HasAura(LIVINGBOMB, me->GetGUID()) && 
                doCast(opponent, LIVINGBOMB))
            {
                Living_Bomb_cd = 6000;
                GC_Timer = 500;
                return;
            }
            //cone of cold
            if (CONEOFCOLD && ConeofCold_cd <= diff && GC_Timer <= diff && dist < 7 && 
                me->HasInArc(M_PI, opponent) && 
                doCast(opponent, CONEOFCOLD))
            {
                ConeofCold_cd = 14000;
                GC_Timer = 500;
                return;
            }
            //dragon's breath
            u = me->SelectNearestTarget(7);
            if (DRAGONBREATH && u && DragonBreath_cd <= diff && GC_Timer <= diff && 
                me->HasInArc(M_PI, opponent) && !HasAuraName(u, FROSTNOVA) && 
                doCast(opponent, DRAGONBREATH))
            {
                DragonBreath_cd = 25000;
                GC_Timer = 800;
                return;
            }
            /*//blast wave //TODO Separate again
            u = me->SelectNearestTarget(8);
            if (BLASTWAVE != 0 && u && isTimerReady(BlastWave_cd) && 
                !HasAuraName(u, FROSTNOVA) && !HasAuraName(u, DRAGONBREATH) && 
                doCast(me, BLASTWAVE))
            {
                BlastWave_cd = BLASTWAVE_CD;
                GC_Timer = 800;
            }*/
            //fire blast
            if (FireBlast_cd <= diff && GC_Timer <= diff && dist < 20 && 
                Rand() < 20 + 80*(!opponent->HasAuraType(SPELL_AURA_MOD_STUN) && me->HasAura(IMPACT_BUFF)) && 
                doCast(opponent, FIREBLAST))
            {
                FireBlast_cd = 6000;
                GC_Timer = 500;
                return;
            }
            //flamestrike
            if (GC_Timer <= diff && Rand() < 60 && me->HasAura(FIRESTARTERBUFF))
            {
                Unit* FStarget = FindAOETarget(30, true, false);
                if (FStarget && doCast(FStarget, FLAMESTRIKE, true))
                {
                    me->RemoveAurasDueToSpell(FIRESTARTERBUFF);
                    GC_Timer = 0;
                    return;
                }
            }
            //blizzard
            if (BLIZZARD && Rand() < 80 && Blizzard_cd <= diff)
            {
                Unit* blizztarget = FindAOETarget(30, true);
                if (blizztarget && doCast(blizztarget, BLIZZARD))
                {
                    Blizzard_cd = 5000;
                    return;
                }
                Blizzard_cd = 2000;//fail
            }
            //Frost of Fire Bolt
            if (Rand() < 75 && Bolt_cd <= diff && dist < 30 && 
                doCast(opponent, BOLT))
            {
                Bolt_cd = uint32(float(sSpellMgr->GetSpellInfo(BOLT)->CalcCastTime()/100) * me->GetFloatValue(UNIT_MOD_CAST_SPEED) + 200);
                return;
            }
            //Arcane Missiles
            if (Rand() < 10 && GC_Timer <= diff && !me->isMoving() && dist < 20 && 
                doCast(opponent, ARCANEMISSILES))
                return;
        }
Пример #14
0
void noFighting::HandleEvent(const unsigned int id)
{
    // Normales Ablaufevent?
    if(id == 0)
    {
        switch(turn)
        {
            case 2:
            {
                // Der Kampf hat gerade begonnen

                // "Auslosen", wer als erstes dran ist mit Angreifen
                turn = static_cast<unsigned char>(RANDOM.Rand(__FILE__, __LINE__, obj_id, 2));
                // anfangen anzugreifen
                StartAttack();
            } return;
            case 0:
            case 1:
            {
                // Sounds löschen von der letzten Kampfphase
                SoundManager::inst().WorkingFinished(this);

                // Wurde der eine getroffen?
                if(defending_animation == 3)
                {
                    if(--soldiers[!turn]->hitpoints == 0)
                    {
                        // Soldat Bescheid sagen, dass er stirbt
                        soldiers[!turn]->LostFighting();
                        // Anderen Soldaten auf die Karte wieder setzen, Bescheid sagen, er kann wieder loslaufen
                        gwg->AddFigure(soldiers[turn], soldiers[turn]->GetX(), soldiers[turn]->GetY());
                        soldiers[turn]->WonFighting();
                        // Besitzer merken für die Sichtbarkeiten am Ende dann
                        player_won = soldiers[turn]->GetPlayer();
                        soldiers[turn] = 0;
                        // Hitpoints sind 0 --> Soldat ist tot, Kampf beendet, turn = 3+welche Soldat stirbt
                        turn = 3 + (!turn);
                        // Event zum Sterben des einen Soldaten anmelden
                        current_ev = em->AddEvent(this, 30);
                        // Umstehenden Figuren Bescheid nach gewisser Zeit Bescheid sagen
                        /*em->AddEvent(this,RELEASE_FIGURES_OFFSET,1);*/
                        gwg->RoadNodeAvailable(soldiers[turn - 3]->GetX(), soldiers[turn - 3]->GetY());

                        // In die Statistik eintragen
                        gwg->GetPlayer(player_won)->ChangeStatisticValue(STAT_VANQUISHED, 1);
                        return;
                    }
                }

                turn = !turn;
                StartAttack();
            } return;
            case 3:
            case 4:
            {
                unsigned player_lost = turn - 3;
                MapCoord x = soldiers[player_lost]->GetX(), y = soldiers[player_lost]->GetY();

                // Sounds löschen vom Sterben
                SoundManager::inst().WorkingFinished(this);

                // Kampf ist endgültig beendet
                em->AddToKillList(this);
                gwg->RemoveFigure(this, x, y);

                // Wenn da nix war bzw. nur ein Verzierungsobjekt, kommt nun ein Skelett hin
                noBase* no = gwg->GetNO(x, y);
                if(no->GetType() == NOP_NOTHING || no->GetType() == NOP_ENVIRONMENT)
                {
                    if(no->GetType() != NOP_NOTHING)
                    {
                        no->Destroy();
                        delete no;
                    }

                    gwg->SetNO(new noSkeleton(x, y), x, y);
                }

                // Umstehenden Figuren Bescheid sagen
                //gwg->RoadNodeAvailable(soldiers[turn-3]->GetX(),soldiers[turn-3]->GetY());

                // Sichtradius ausblenden am Ende des Kampfes, an jeweiligen Soldaten dann übergeben, welcher überlebt hat
                gwg->RecalcVisibilitiesAroundPoint(x, y, VISUALRANGE_SOLDIER, soldiers[player_lost]->GetPlayer(), NULL);
                gwg->RecalcVisibilitiesAroundPoint(x, y, VISUALRANGE_SOLDIER, player_won, NULL);

                // Soldaten endgültig umbringen
                gwg->GetPlayer(soldiers[player_lost]->GetPlayer())->DecreaseInventoryJob(soldiers[player_lost]->GetJobType(), 1);
                soldiers[player_lost]->Destroy();
                delete soldiers[player_lost];



            } break;
        }
    }
    // Figur-Weiterlauf-Event
    else if(id == 1)
    {
        //// Figuren weiterlaufen lassen
        //gwg->RoadNodeAvailable(soldiers[turn-3]->GetX(),soldiers[turn-3]->GetY());
    }
}
Пример #15
0
void MeleeCombatTask::PerformReady(idAI* owner)
{
	// the "ready" state is where we decide whether to attack or parry
	// For now, always attack
	CMeleeStatus& ownerStatus = owner->m_MeleeStatus;

	idActor* enemy = _enemy.GetEntity();
	CMeleeStatus& enemyStatus = enemy->m_MeleeStatus;

	if( cv_melee_state_debug.GetBool() )
	{
		idStr debugText = "MeleeAction: Ready";
		gameRenderWorld->DrawText( debugText, (owner->GetEyePosition() - owner->GetPhysics()->GetGravityNormal()*-25), 0.20f, colorMagenta, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1, gameLocal.msec );
	}

	// TODO: Cache these rather than calc. every frame?
	int NextAttTime;
	if( ownerStatus.m_ActionResult == MELEERESULT_PAR_BLOCKED 
		|| ownerStatus.m_ActionResult == MELEERESULT_PAR_ABORTED )
	{
		// just parried, so use the riposte recovery time for the attack
		NextAttTime = ownerStatus.m_LastActTime + owner->m_MeleeCurrentRiposteRecovery;
	}
	// longer recovery if we were parried
	else if( ownerStatus.m_ActionResult == MELEERESULT_AT_PARRIED )
	{
		NextAttTime = ownerStatus.m_LastActTime + owner->m_MeleeCurrentAttackLongRecovery;
	}
	else
	{
		NextAttTime = ownerStatus.m_LastActTime + owner->m_MeleeCurrentAttackRecovery;
	}

	int NextParTime = ownerStatus.m_LastActTime + owner->m_MeleeCurrentParryRecovery;

	// ATTACK: If the timer allows us and if the enemy is in range
	if (gameLocal.time > NextAttTime 
		&& (owner->GetMemory().canHitEnemy || owner->GetMemory().willBeAbleToHitEnemy)
		&& !_bForceParry )
	{
		StartAttack(owner);
	}

	// PARRY:
	// If we can't attack and our enemy is attacking in range
	// and if the attack is still dangerous (not recovering)
	// TODO: Figure out how to switch enemies to face & parry a new one
	else if
		( 
			ownerStatus.m_bCanParry
			&& gameLocal.time > NextParTime
			&& (enemyStatus.m_ActionState == MELEEACTION_ATTACK)
			&& (enemyStatus.m_ActionPhase != MELEEPHASE_RECOVERING)
			&& owner->GetMemory().canBeHitByEnemy
			&& !_bForceAttack
			&& !_EnemyUsesUnarmedCombat // grayman #3331 - skip parries if enemy uses unarmed melee combat
		)
	{
		// check if our enemy made the same attack before
		EMeleeType AttType = enemyStatus.m_ActionType;
		if ( ( _PrevEnemy.GetEntity() == enemy ) && ( _PrevAttParried == AttType )
			&& (gameLocal.time - _PrevAttTime) < owner->m_MeleeRepAttackTime )
		{
			_NumAttReps++;
			// reset timer for next attack
			_PrevAttTime = gameLocal.time; 
		}
		else
		{
			// attack was new
			_PrevEnemy = enemy;
			_PrevAttParried = AttType;
			_PrevAttTime = gameLocal.time;
			_NumAttReps = 1;
		}

		// Counter attack if enemy is in range and chance check succeeds
		if( (owner->GetMemory().canHitEnemy || owner->GetMemory().willBeAbleToHitEnemy)
			&& gameLocal.random.RandomFloat() < owner->m_MeleeCounterAttChance )
		{
			StartAttack(owner);
		}
		else
		{
			// normal procedure, parry rather than counter attack
			StartParry(owner);
		}
	}
	else
	{
		// If we can't attack or parry, wait until we can
	}
}