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; } } }
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(); } }
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; } } }
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); } }
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; } } }
//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(); } }
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(); } }
void EnterCombat(Unit* /*who*/) override { _EnterCombat(); StartAttack(); }
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; }
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; }
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); }
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; }
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; }
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()); } }
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 } }