void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; DoMeleeAttackIfReady(); if (ChaseTimer <= diff) { if (!IsChasing) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) { Talk(SAY_WOLF_HOOD); DoCast(target, SPELL_LITTLE_RED_RIDING_HOOD, true); TempThreat = GetThreat(target); if (TempThreat) ModifyThreatByPercent(target, -100); HoodGUID = target->GetGUID(); AddThreat(target, 1000000.0f); ChaseTimer = 20000; IsChasing = true; } } else { IsChasing = false; if (Unit* target = ObjectAccessor::GetUnit(*me, HoodGUID)) { HoodGUID.Clear(); if (GetThreat(target)) ModifyThreatByPercent(target, -100); AddThreat(target, TempThreat); TempThreat = 0; } ChaseTimer = 40000; } } else ChaseTimer -= diff; if (IsChasing) return; if (FearTimer <= diff) { DoCastVictim(SPELL_TERRIFYING_HOWL); FearTimer = urand(25000, 35000); } else FearTimer -= diff; if (SwipeTimer <= diff) { DoCastVictim(SPELL_WIDE_SWIPE); SwipeTimer = urand(25000, 30000); } else SwipeTimer -= diff; }
// // Evaluate enemy threat to the given defense table // U32 Map::Cluster::EvaluateThreat(Team *team, Relation relation, U32 armourClass) { U32 threat = 0; // Enumerate the enemy teams for (List<Team>::Iterator t(&team->RelatedTeams(relation)); *t; ++t) { threat += GetThreat((*t)->GetId(), armourClass); } return (threat); }
double MapAnalysis::GetThreatRank(const CityData * city) const { Assert(city); PLAYER_INDEX owner = city->GetOwner(); sint32 threat = GetThreat(owner, city->GetHomeCity().RetPos()); if ((m_maxCityThreat[owner] - m_minCityThreat[owner]) > 0) return ((double)(threat - m_minCityThreat[owner]) / (double)(m_maxCityThreat[owner] - m_minCityThreat[owner])); return 0.0; }
// // Evaluate enemy threat to the given defense table // U32 Map::Cluster::EvaluateThreat(Team *team, Relation relation, U32 *defenses) { U32 threat = 0; // Enumerate the enemy teams for (List<Team>::Iterator t(&team->RelatedTeams(relation)); *t; ++t) { for (U32 a = 0; a < ArmourClass::NumClasses(); a++) { if (defenses[a]) { threat += GetThreat((*t)->GetId(), a) * defenses[a]; } } } return (threat); }
void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; events.Update(diff); while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_CLEAVE: DoCastVictim(SPELL_CLEAVE); events.ScheduleEvent(EVENT_CLEAVE, 7s); break; case EVENT_BLASTWAVE: DoCastVictim(SPELL_BLASTWAVE); events.ScheduleEvent(EVENT_BLASTWAVE, 8s, 16s); break; case EVENT_MORTALSTRIKE: DoCastVictim(SPELL_MORTALSTRIKE); events.ScheduleEvent(EVENT_MORTALSTRIKE, 25s, 35s); break; case EVENT_KNOCKBACK: DoCastVictim(SPELL_KNOCKBACK); if (GetThreat(me->GetVictim())) ModifyThreatByPercent(me->GetVictim(), -50); events.ScheduleEvent(EVENT_KNOCKBACK, 15s, 30s); break; case EVENT_CHECK: if (me->GetDistance(me->GetHomePosition()) > 150.0f) { Talk(SAY_LEASH); EnterEvadeMode(EVADE_REASON_BOUNDARY); } events.ScheduleEvent(EVENT_CHECK, 1s); break; } } DoMeleeAttackIfReady(); }
double MapAnalysis::CityAtRiskRatio(const Unit city, const PLAYER_INDEX opponentId) const { Assert(city.IsValid()); PLAYER_INDEX playerId = city.GetOwner(); Player * player_ptr = g_player[playerId]; if (player_ptr == NULL) return 0.0; if (opponentId != PLAYER_UNASSIGNED && g_player[opponentId] == NULL) return 0.0; MapPoint pos; city.GetPos(pos); sint32 player_threat = m_threatGrid[playerId].GetGridValue(pos); sint32 opponent_threat = (PLAYER_UNASSIGNED == opponentId) // In that case no opponent there, so it is the right way to calculate it? ? GetThreat(playerId, pos) : m_threatGrid[opponentId].GetGridValue(pos); double ratio; if (player_threat > 0) { ratio = ((double) opponent_threat / (double) player_threat) * 0.2; if (ratio > 1.0) ratio = 1.0; else if (ratio < 0.0) ratio = 0.0; } else if (opponent_threat <= 0) { ratio = 0.0; } else { ratio = 1.0; } return ratio; }
void UpdateAI(uint32 diff) override { //Return since we have no target if (!UpdateVictim()) return; //Charge_Timer if (Charge_Timer <= diff) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { DoCast(target, SPELL_CHARGE); //me->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true, 1); AttackStart(target); } Charge_Timer = urand(8000, 16000); } else Charge_Timer -= diff; //KnockBack_Timer if (KnockBack_Timer <= diff) { DoCastVictim(SPELL_KNOCKBACK); if (GetThreat(me->GetVictim())) ModifyThreatByPercent(me->GetVictim(), -80); KnockBack_Timer = urand(15000, 25000); } else KnockBack_Timer -= diff; //Enrage_Timer if (!Enraged && Enrage_Timer <= diff) { DoCast(me, SPELL_ENRAGE); Enraged = true; } else Charge_Timer -= diff; DoMeleeAttackIfReady(); }
void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) return; while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_SHADOWFLAME: DoCastVictim(SPELL_SHADOWFLAME); events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000)); break; case EVENT_WINGBUFFET: DoCastVictim(SPELL_WINGBUFFET); if (GetThreat(me->GetVictim())) ModifyThreatByPercent(me->GetVictim(), -75); events.ScheduleEvent(EVENT_WINGBUFFET, 30000); break; case EVENT_FRENZY: Talk(EMOTE_FRENZY); DoCast(me, SPELL_FRENZY); events.ScheduleEvent(EVENT_FRENZY, urand(8000, 10000)); break; } if (me->HasUnitState(UNIT_STATE_CASTING)) return; } DoMeleeAttackIfReady(); }
void DoAction(int32 actionId) override { if (actionId == ACTION_STORE_OLD_TARGET) { if (Unit* victim = me->GetVictim()) { _oldTargetGUID = victim->GetGUID(); _tempThreat = GetThreat(victim); } } else if (actionId == ACTION_RESET_THREAT) { if (Unit* oldTarget = ObjectAccessor::GetUnit(*me, _oldTargetGUID)) { if (Unit* current = me->GetVictim()) ModifyThreatByPercent(current, -100); AddThreat(oldTarget, _tempThreat); AttackStart(oldTarget); _oldTargetGUID.Clear(); _tempThreat = 0.0f; } } }
void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) return; while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_BRAIN_WASH_TOTEM: DoCast(me, SPELL_BRAIN_WASH_TOTEM); events.ScheduleEvent(EVENT_BRAIN_WASH_TOTEM, 18s, 26s); break; case EVENT_POWERFULL_HEALING_WARD: DoCast(me, SPELL_POWERFULL_HEALING_WARD); events.ScheduleEvent(EVENT_POWERFULL_HEALING_WARD, 14s, 20s); break; case EVENT_HEX: if (Unit* target = me->GetVictim()) { DoCast(target, SPELL_HEX, true); if (GetThreat(target)) ModifyThreatByPercent(target, -80); } events.ScheduleEvent(EVENT_HEX, 12s, 20s); break; case EVENT_DELUSIONS_OF_JINDO: // Casting the delusion curse with a shade so shade will attack the same target with the curse. if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) { DoCast(target, SPELL_SHADE_OF_JINDO, true); DoCast(target, SPELL_DELUSIONS_OF_JINDO); } events.ScheduleEvent(EVENT_DELUSIONS_OF_JINDO, 4s, 12s); break; case EVENT_TELEPORT: // Teleports a random player and spawns 9 Sacrificed Trolls to attack player if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) { DoTeleportPlayer(target, TeleportLoc.GetPositionX(), TeleportLoc.GetPositionY(), TeleportLoc.GetPositionZ(), TeleportLoc.GetOrientation()); if (GetThreat(me->GetVictim())) ModifyThreatByPercent(target, -100); // Summon a formation of trolls for (uint8 i = 0; i < 10; ++i) if (Creature* SacrificedTroll = me->SummonCreature(NPC_SACRIFICED_TROLL, Formation[i].GetPositionX(), Formation[i].GetPositionY(), Formation[i].GetPositionZ(), Formation[i].GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000)) SacrificedTroll->AI()->AttackStart(target); } events.ScheduleEvent(EVENT_TELEPORT, 15s, 23s); break; default: break; } if (me->HasUnitState(UNIT_STATE_CASTING)) return; } DoMeleeAttackIfReady(); }
void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; //Invisible_Timer if (Invisible_Timer <= diff) { me->InterruptSpell(CURRENT_GENERIC_SPELL); SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); me->SetDisplayId(11686); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); Invisible = true; Invisible_Timer = urand(15000, 30000); } else Invisible_Timer -= diff; if (Invisible) { if (Ambush_Timer <= diff) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) { DoTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()); DoCast(target, SPELL_AMBUSH); } Ambushed = true; Ambush_Timer = 3000; } else Ambush_Timer -= diff; } if (Ambushed) { if (Visible_Timer <= diff) { me->InterruptSpell(CURRENT_GENERIC_SPELL); me->SetDisplayId(15268); SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); Invisible = false; Visible_Timer = 4000; } else Visible_Timer -= diff; } //Resetting some aggro so he attacks other gamers if (!Invisible) { if (Aggro_Timer <= diff) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) { if (GetThreat(me->GetVictim())) ModifyThreatByPercent(me->GetVictim(), -50); AttackStart(target); } Aggro_Timer = urand(7000, 20000); } else Aggro_Timer -= diff; if (ThousandBlades_Timer <= diff) { DoCastVictim(SPELL_THOUSANDBLADES); ThousandBlades_Timer = urand(7000, 12000); } else ThousandBlades_Timer -= diff; } DoMeleeAttackIfReady(); }
void MapAnalysis::BeginTurn() { MapPoint pos; Army army; Unit city; Unit unit; sint32 i; m_piracyIncomeMatrix.assign(m_piracyIncomeMatrix.size(), 0); m_cityOnContinent.Reset(FALSE); m_armyOnContinent.Reset(FALSE); m_worldPopulation = 0; ComputeHandicapRatios(); size_t player; for (player = 0; player < m_threatGrid.size(); ++player) { m_threatGrid [player].Clear(); m_attackGrid [player].Clear(); m_defenseGrid [player].Clear(); m_rangedGrid [player].Clear(); m_bombardLandGrid [player].Clear(); m_bombardSeaGrid [player].Clear(); m_bombardAirGrid [player].Clear(); m_valueGrid [player].Clear(); m_tradeAtRiskGrid [player].Clear(); m_piracyLossGrid [player].Clear(); m_minCityThreat [player] = std::numeric_limits<sint32>::max(); m_maxCityThreat [player] = std::numeric_limits<sint32>::min(); m_movementTypeUnion[player] = 0x0; m_nuclearWeapons [player] = 0; m_bioWeapons [player] = 0; m_nanoWeapons [player] = 0; m_specialAttackers [player] = 0; m_continentSize [player] = 0; m_totalPopulation [player] = 0; m_landArea [player] = 0; m_totalTrade [player] = 0; Player * player_ptr = g_player[player]; if (player_ptr == NULL) continue; RecalcCityRanks(player); m_projectedScience[player] = player_ptr->m_advances->GetProjectedScience(); m_totalPopulation[player] = static_cast<sint16>(player_ptr->GetTotalPopulation()); m_landArea[player] = static_cast<sint16>(player_ptr->GetLandArea()); m_worldPopulation += m_totalPopulation[player]; sint32 num_units = player_ptr->m_all_units->Num(); for (i = 0; i < num_units; i++) { unit = player_ptr->m_all_units->Access(i); Assert(unit.IsValid()); if ( unit.IsValid() && unit.GetDBRec() && unit.GetDBRec()->GetNumSpecialAttacks() > 0 ) { m_specialAttackers[player]++; } } sint32 num_armies = player_ptr->m_all_armies->Num(); for (i = 0; i < num_armies; i++) { army = player_ptr->m_all_armies->Access(i); Assert(army.IsValid()); army->GetPos(pos); sint8 defense_count; sint8 ranged_count; float attack_strength; float defense_strength; float ranged_strength; float bombard_land_strength; float bombard_sea_strength; float bombard_air_strength; float total_value; army->ComputeStrength(attack_strength, defense_strength, ranged_strength, defense_count, ranged_count, bombard_land_strength, bombard_sea_strength, bombard_air_strength, total_value, false ); Assert(total_value >= 0); m_nuclearWeapons[player] += army->CountNuclearUnits(); m_bioWeapons[player] += army->CountBioUnits(); m_nanoWeapons[player] += army->CountNanoUnits(); if(m_empireCenter[player] == MapPoint()) { CalcEmpireCenter(player); } if(!m_empireBoundingRect[player].IsValid()) { UpdateBoundingRectangle(army); } m_threatGrid [player].AddValue(pos, static_cast<sint32>(attack_strength + ranged_strength)); m_attackGrid [player].AddValue(pos, static_cast<sint32>(attack_strength)); m_defenseGrid [player].AddValue(pos, static_cast<sint32>(defense_strength)); m_rangedGrid [player].AddValue(pos, static_cast<sint32>(ranged_strength)); m_bombardLandGrid [player].AddValue(pos, static_cast<sint32>(bombard_land_strength)); m_bombardSeaGrid [player].AddValue(pos, static_cast<sint32>(bombard_sea_strength)); m_bombardAirGrid [player].AddValue(pos, static_cast<sint32>(bombard_air_strength)); m_valueGrid [player].AddValue(pos, static_cast<sint32>(total_value)); bool is_land; sint16 cont; g_theWorld->GetContinent(pos, cont, is_land); if(is_land) { bool is_military = (attack_strength > 0 || ranged_strength > 0) && !army->IsCivilian(); if(is_military) { m_armyOnContinent.Set(player, cont, TRUE); } } m_movementTypeUnion[player] |= army.GetMovementType(); Assert(m_threatGrid [player].GetTotalValue() >= 0); Assert(m_attackGrid [player].GetTotalValue() >= 0); Assert(m_defenseGrid [player].GetTotalValue() >= 0); Assert(m_rangedGrid [player].GetTotalValue() >= 0); Assert(m_bombardLandGrid [player].GetTotalValue() >= 0); Assert(m_bombardSeaGrid [player].GetTotalValue() >= 0); Assert(m_bombardAirGrid [player].GetTotalValue() >= 0); Assert(m_valueGrid [player].GetTotalValue() >= 0); Assert(m_nuclearWeapons [player] >= 0); Assert(m_bioWeapons [player] >= 0); Assert(m_nanoWeapons [player] >= 0); Assert(m_specialAttackers[player] >= 0); Assert(m_continentSize [player] >= 0); Assert(m_totalPopulation [player] >= 0); Assert(m_landArea [player] >= 0); Assert(m_totalTrade [player] >= 0); } sint32 num_cities = player_ptr->m_all_cities->Num(); for (i = 0; i < num_cities; i++) { city = player_ptr->m_all_cities->Access(i); Assert(city.IsValid() && city->GetCityData()); city.GetPos(pos); sint32 total_value = city->GetCityData()->GetValue(); m_totalTrade[player] += city->GetCityData()->GetGoldFromTradeRoutes(); m_valueGrid[player].AddValue(pos, total_value); TradeDynamicArray * trade_routes = city.CD()->GetTradeSourceList(); Assert(trade_routes != NULL); sint32 tradeRouteCount = trade_routes ? trade_routes->Num() : 0; for (sint32 j = 0; j < tradeRouteCount; j++) { sint32 route_value = trade_routes->Get(j)->GetValue(); Army pirate_army = trade_routes->Get(j)->GetPiratingArmy(); if (pirate_army.IsValid()) { m_piracyLossGrid[player]. AddValue(pirate_army->RetPos(), route_value); AddPiracyIncome(pirate_army.GetOwner(), player, static_cast<sint16>(route_value)); m_valueGrid[pirate_army.GetOwner()]. AddValue(pirate_army->RetPos(), route_value); } const DynamicArray < MapPoint > * path = trade_routes->Get(j)->GetPath(); sint32 per_cell_value = (sint32)(((double)route_value / path->Num()) * 1000.0); for (sint32 k = 0; k < path->Num(); k++) { m_tradeAtRiskGrid[player].AddValue(path->Get(k), per_cell_value); } } bool is_land; sint16 cont; g_theWorld->GetContinent(pos, cont, is_land); if (is_land) { m_cityOnContinent.Set(player, cont, TRUE); m_continentSize[player] += g_theWorld->GetLandContinentSize(cont) / num_cities; } } } DPRINTF(k_DBG_MAPANALYSIS, ("BEFORE RELAX:\n")); DebugLog(); DPRINTF(k_DBG_MAPANALYSIS, ("\n")); const sint8 cycles = 1; const float coef = 0.95f; for (player = 0; player < m_threatGrid.size(); player++) { m_threatGrid [player].Relax(cycles, coef); m_attackGrid [player].Relax(cycles, coef); m_defenseGrid [player].Relax(cycles, coef); m_rangedGrid [player].Relax(cycles, coef); m_bombardLandGrid [player].Relax(cycles, coef); m_bombardSeaGrid [player].Relax(cycles, coef); m_bombardAirGrid [player].Relax(cycles, coef); m_valueGrid [player].Relax(cycles, coef); } for (player = 0; player < m_threatGrid.size(); player++) { if(Diplomat::HasDiplomat(player)) { Diplomat::GetDiplomat(player).ComputeAllDesireWarWith(); Diplomat::GetDiplomat(player).ComputeIncursionPermission(); } } for (player = 0; player < m_threatGrid.size(); player++) { Player * player_ptr = g_player[player]; if (player_ptr == NULL) continue; sint32 num_cities = player_ptr->m_all_cities->Num(); for (i = 0; i < num_cities; i++) { city = player_ptr->m_all_cities->Access(i); // Threat has to be calculated after relax sint32 threat = GetThreat(player, city.RetPos()); if (threat < m_minCityThreat[player]) m_minCityThreat[player] = threat; if (threat > m_maxCityThreat[player]) m_maxCityThreat[player] = threat; } } DPRINTF(k_DBG_MAPANALYSIS, ("RELAXED:\n")); DebugLog(); DPRINTF(k_DBG_MAPANALYSIS, ("\n")); }
void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; //SweepingStrikes_Timer if (SweepingStrikes_Timer <= diff) { DoCastVictim(SPELL_SWEEPINGSTRIKES); SweepingStrikes_Timer = 22000 + rand32() % 4000; } else SweepingStrikes_Timer -= diff; //SinisterStrike_Timer if (SinisterStrike_Timer <= diff) { DoCastVictim(SPELL_SINISTERSTRIKE); SinisterStrike_Timer = 8000 + rand32() % 8000; } else SinisterStrike_Timer -= diff; //Gouge_Timer if (Gouge_Timer <= diff) { DoCastVictim(SPELL_GOUGE); if (GetThreat(me->GetVictim())) ModifyThreatByPercent(me->GetVictim(), -100); Gouge_Timer = 17000 + rand32() % 10000; } else Gouge_Timer -= diff; //Kick_Timer if (Kick_Timer <= diff) { DoCastVictim(SPELL_KICK); Kick_Timer = 15000 + rand32() % 10000; } else Kick_Timer -= diff; //Blind_Timer if (Blind_Timer <= diff) { DoCastVictim(SPELL_BLIND); Blind_Timer = 10000 + rand32() % 10000; } else Blind_Timer -= diff; //Check_Timer for the death of LorKhan and Zath. if (!FakeDeath && Check_Timer <= diff) { if (instance->GetBossState(DATA_LORKHAN) == SPECIAL) { //Resurrect LorKhan if (Unit* pLorKhan = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_LORKHAN))) { pLorKhan->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); pLorKhan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); pLorKhan->SetFaction(14); pLorKhan->SetFullHealth(); } } if (instance->GetBossState(DATA_THEKAL) == SPECIAL) { //Resurrect Thekal if (Unit* pThekal = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_THEKAL))) { pThekal->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); pThekal->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); pThekal->SetFaction(14); pThekal->SetFullHealth(); } } Check_Timer = 5000; } else Check_Timer -= diff; if (!HealthAbovePct(5)) { me->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE_PERCENT); me->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE); me->RemoveAurasByType(SPELL_AURA_PERIODIC_LEECH); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetStandState(UNIT_STAND_STATE_SLEEP); me->SetFaction(35); me->AttackStop(); instance->SetBossState(DATA_ZATH, SPECIAL); FakeDeath = true; } DoMeleeAttackIfReady(); }