예제 #1
0
/*
================
rvTramGate::Event_Touch
================
*/
void rvTramGate::Event_Touch( idEntity* other, trace_t* trace ) {
	if( !IsDoorMasterValid() ) {
		return;
	}

	if( IsClosed() ) {
		OpenGate();
		GetDoorMaster()->ProcessEvent( &EV_Touch, this, trace );	
	} else if( IsOpen() ) {
		GetDoorMaster()->ProcessEvent( &EV_Touch, this, trace );	
	}
}
예제 #2
0
 void DoAction(int32 action) override
 {
     switch (action)
     {
         case ACTION_MINION_EVADE:
             if (_gateIsOpen || me->getThreatManager().isThreatListEmpty())
                 return EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
             if (_gateCanOpen)
                 OpenGate();
             break;
     }
 }
예제 #3
0
/*
================
rvTramGate::Event_OpenGate
================
*/
void rvTramGate::Event_OpenGate() {
	OpenGate();
}
예제 #4
0
            void UpdateAI(uint32 diff) override
            {
                if (!UpdateVictim())
                    return;

                if (me->HasReactState(REACT_AGGRESSIVE) && !_gateIsOpen && !IsOnSameSide(me, me->GetVictim()))
                {
                    // NBD: this should only happen in practice if there is nobody left alive on our side (we should open gate)
                    // thus we only do a cursory check to make sure (edge cases?)
                    if (Player* newTarget = FindEligibleTarget(me, _gateIsOpen))
                    {
                        me->getThreatManager().resetAllAggro();
                        me->AddThreat(newTarget, 1.0f);
                        AttackStart(newTarget);
                    }
                    else
                        OpenGate();
                }

                events.Update(diff);

                if (!_gateIsOpen && HealthBelowPct(30) && events.IsInPhase(PHASE_TWO))
                    OpenGate();

                while (uint32 eventId = events.ExecuteEvent())
                {
                    switch (eventId)
                    {
                        case EVENT_SUMMON:
                        {
                            if (RAID_MODE(waves10,waves25).size() <= _waveCount) // bounds check
                            {
                                TC_LOG_INFO("scripts", "GothikAI: Wave count %d is out of range for difficulty %d.", _waveCount, GetDifficulty());
                                break;
                            }
                            
                            std::list<Creature*> triggers;
                            me->GetCreatureListWithEntryInGrid(triggers, NPC_TRIGGER, 150.0f);
                            for (GothikWaveEntry entry : RAID_MODE(waves10, waves25)[_waveCount].first)
                                for (uint8 i = 0; i < entry.second; ++i)
                                {
                                    // GUID layout is as follows:
                                    // CGUID+4: center (back of platform) - primary rider spawn
                                    // CGUID+5: north (back of platform) - primary knight spawn
                                    // CGUID+6: center (front of platform) - second spawn
                                    // CGUID+7: south (front of platform) - primary trainee spawn
                                    uint32 targetDBGuid;
                                    switch (entry.first)
                                    {
                                        case NPC_LIVE_RIDER: // only spawns from center (back) > north
                                            targetDBGuid = (CGUID_TRIGGER + 4) + (i % 2);
                                            break;
                                        case NPC_LIVE_KNIGHT: // spawns north > center (front) > south
                                            targetDBGuid = (CGUID_TRIGGER + 5) + (i % 3);
                                            break;
                                        case NPC_LIVE_TRAINEE: // spawns south > center (front) > north
                                            targetDBGuid = (CGUID_TRIGGER + 7) - (i % 3);
                                            break;
                                        default:
                                            targetDBGuid = 0;
                                    }
                                
                                    for (Creature* trigger : triggers)
                                        if (trigger && trigger->GetSpawnId() == targetDBGuid)
                                        {
                                            DoSummon(entry.first, trigger, 1.0f, 15 * IN_MILLISECONDS, TEMPSUMMON_CORPSE_TIMED_DESPAWN);
                                            break;
                                        }
                                }

                            if (uint8 timeToNext = RAID_MODE(waves10, waves25)[_waveCount].second)
                                events.ScheduleEvent(EVENT_SUMMON, timeToNext * IN_MILLISECONDS, 0, PHASE_ONE);

                            ++_waveCount;
                            break;
                        }
                        case EVENT_DOORS_UNLOCK:
                            _gateCanOpen = true;
                            for (ObjectGuid summonGuid : summons)
                                if (Creature* summon = ObjectAccessor::GetCreature(*me, summonGuid))
                                    if (summon->IsAlive() && (!summon->IsInCombat() || summon->IsInEvadeMode()))
                                    {
                                        OpenGate();
                                        break;
                                    }
                            break;
                        case EVENT_PHASE_TWO:
                            events.SetPhase(PHASE_TWO);
                            events.ScheduleEvent(EVENT_TELEPORT, 20 * IN_MILLISECONDS, 0, PHASE_TWO);
                            events.ScheduleEvent(EVENT_HARVEST, 15 * IN_MILLISECONDS, 0, PHASE_TWO);
                            events.ScheduleEvent(EVENT_RESUME_ATTACK, 2 * IN_MILLISECONDS, 0, PHASE_TWO);
                            Talk(SAY_PHASE_TWO);
                            Talk(EMOTE_PHASE_TWO);
                            me->SetReactState(REACT_PASSIVE);
                            me->getThreatManager().resetAllAggro();
                            DoCastAOE(SPELL_TELEPORT_LIVE);
                            break;
                        case EVENT_TELEPORT:
                            if (!HealthBelowPct(30))
                            {
                                me->CastStop();
                                me->AttackStop();
                                me->StopMoving();
                                me->SetReactState(REACT_PASSIVE);
                                me->getThreatManager().resetAllAggro();
                                DoCastAOE(_lastTeleportDead ? SPELL_TELEPORT_LIVE : SPELL_TELEPORT_DEAD);
                                _lastTeleportDead = !_lastTeleportDead;

                                events.CancelEvent(EVENT_BOLT);
                                events.ScheduleEvent(EVENT_TELEPORT, 20 * IN_MILLISECONDS, 0, PHASE_TWO);
                                events.ScheduleEvent(EVENT_RESUME_ATTACK, 2 * IN_MILLISECONDS, 0, PHASE_TWO);
                            }
                            break;

                        case EVENT_HARVEST:
                            DoCastAOE(SPELL_HARVEST_SOUL, true); // triggered allows this to go "through" shadow bolt
                            events.ScheduleEvent(EVENT_HARVEST, 15 * IN_MILLISECONDS, 0, PHASE_TWO);
                            break;
                        case EVENT_RESUME_ATTACK:
                            me->SetReactState(REACT_AGGRESSIVE);
                            events.ScheduleEvent(EVENT_BOLT, 0, 0, PHASE_TWO);
                            // return to the start of this method so victim side etc is re-evaluated
                            return UpdateAI(0u); // tail recursion for efficiency
                        case EVENT_BOLT:
                            DoCastVictim(SPELL_SHADOW_BOLT);
                            events.ScheduleEvent(EVENT_BOLT, 1 * IN_MILLISECONDS, 0, PHASE_TWO);
                            break;
                        case EVENT_INTRO_2:
                            Talk(SAY_INTRO_2);
                            break;
                        case EVENT_INTRO_3:
                            Talk(SAY_INTRO_3);
                            break;
                        case EVENT_INTRO_4:
                            Talk(SAY_INTRO_4);
                            break;
                    }
                }
            }