void CharacterUpdaterAI::recieveCollisionFrom(CCObjectCollideable *collisionSource) { if( waypointCycle == cycle_random ) { nextWaypoint(); } else if( waypointCycle == cycle_aiNodes ) { wait = 0.0f; pickRandomNode(); } else if( waypointCycle == cycle_inOrder ) { nextWaypoint(); } else { waypointCycle = waypointCycle; } }
void UpdateAI(uint32 const diff) { if (!UpdateVictim()) return; if (me->GetPositionX() > 1140){ if (GameObject* go = me->FindNearestGameObject(207343, 20.0f)){ me->RemoveGameObject(go, true); go->Delete(); Creature* c = me->SummonCreature(43438, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN, 0); //summon corborus c->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); SendAttacker(43438, me->SelectNearestTarget(100.0f)); } } events.Update(diff); if (me->HealthBelowPct(50)){ me->GetMotionMaster()->MovePoint(nextWaypoint(), MillHouseWayPoint[nextWaypoint()][0], MillHouseWayPoint[nextWaypoint()][1], MillHouseWayPoint[nextWaypoint()][2]); me->SetHealth(me->GetMaxHealth()); me->CombatStop(true); events.CancelEvent(EVENT_MILL_FEAR); events.CancelEvent(EVENT_SHADOW_BOLT); events.CancelEvent(EVENT_FROSTBOLT_VOLLEY); events.CancelEvent(EVENT_IMPENDING_DOOM); events.CancelEvent(EVENT_SHADOWFURY); me->SetReactState(REACT_PASSIVE); inMovement = true; if (actualWayPoint == 3){ me->DisappearAndDie(); } else{ events.ScheduleEvent(EVENT_GUARDS, 1000); } } if (me->HasUnitState(UNIT_STATE_CASTING)) return; while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_GUARDS: scheduleEvents(); me->SetReactState(REACT_AGGRESSIVE); return; case EVENT_MILL_FEAR: DoCastRandom(SPELL_FEAR, 0.0f); events.ScheduleEvent(EVENT_MILL_FEAR, 10000); return; case EVENT_SHADOW_BOLT: DoCastVictim(SPELL_SHADOW_BOLT); events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000); return; case EVENT_FROSTBOLT_VOLLEY: DoCast(SPELL_FROSTBOLT_VOLLEY); events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, urand(8000, 15000)); return; case EVENT_IMPENDING_DOOM: DoCast(SPELL_IMPENDING_DOOM); DoCast(me, SPELL_IMPEMDING_DOOM_E, true); events.ScheduleEvent(EVENT_IMPENDING_DOOM, urand(60000, 65000)); return; case EVENT_SHADOWFURY: DoCastRandom(SPELL_SHADOWFURY, 0.0f); events.ScheduleEvent(EVENT_SHADOWFURY, urand(8000, 20000)); return; } } DoMeleeAttackIfReady(); }
mob_millhouse_manastormAI(Creature* creature) : ScriptedAI(creature) { actualWayPoint = nextWaypoint(); }
void Steering::update() { if (mSteeringEnabled) { if (mUpdateNeeded) { updatePath(); } auto entity = mAvatar.getEntity(); if (!mPath.empty()) { const auto& finalDestination = mPath.back(); auto entity3dPosition = entity->getViewPosition(); const WFMath::Point<2> entityPosition(entity3dPosition.x(), entity3dPosition.z()); //First check if we've arrived at our actual destination. if (WFMath::Distance(WFMath::Point<2>(finalDestination.x(), finalDestination.z()), entityPosition) < 0.1f) { //We've arrived at our destination. If we're moving we should stop. if (mLastSentVelocity.isValid() && mLastSentVelocity != WFMath::Vector<2>::ZERO()) { moveInDirection(WFMath::Vector<2>::ZERO()); } stopSteering(); } else { //We should send a move op if we're either not moving, or we've reached a waypoint, or we need to divert a lot. WFMath::Point<2> nextWaypoint(mPath.front().x(), mPath.front().z()); if (WFMath::Distance(nextWaypoint, entityPosition) < 0.1f) { mPath.pop_front(); nextWaypoint = WFMath::Point<2>(mPath.front().x(), mPath.front().z()); } WFMath::Vector<2> velocity = nextWaypoint - entityPosition; WFMath::Point<2> destination; velocity.normalize(); if (mPath.size() == 1) { //if the next waypoint is the destination we should send a "move to position" update to the server, to make sure that we stop when we've arrived. //otherwise, if there's too much lag, we might end up overshooting our destination and will have to double back destination = nextWaypoint; } //Check if we need to divert in order to avoid colliding. WFMath::Vector<2> newVelocity; bool avoiding = mAwareness.avoidObstacles(entityPosition, velocity * mSpeed, newVelocity); if (avoiding) { auto newMag = newVelocity.mag(); auto relativeMag = mSpeed / newMag; velocity = newVelocity; velocity.normalize(); velocity *= relativeMag; mUpdateNeeded = true; } bool shouldSend = false; if (velocity.isValid()) { if (mLastSentVelocity.isValid()) { //If the entity has stopped, and we're not waiting for confirmation to a movement request we've made, we need to start moving. if (!entity->isMoving() && !mExpectingServerMovement) { shouldSend = true; } else { auto currentTheta = std::atan2(mLastSentVelocity.y(), mLastSentVelocity.x()); auto newTheta = std::atan2(velocity.y(), velocity.x()); //If we divert too much from where we need to go we must adjust. if (std::abs(currentTheta - newTheta) > WFMath::numeric_constants<double>::pi() / 20) { shouldSend = true; } } } else { //If we've never sent a movement update before we should do that now. shouldSend = true; } } if (shouldSend) { //If we're moving to a certain destination and aren't avoiding anything we should tell the server to move to the destination. if (destination.isValid() && !avoiding) { moveToPoint(WFMath::Point<3>(destination.x(), entity3dPosition.y(), destination.y())); } else { moveInDirection(velocity); } } } } else { //We are steering, but the path is empty, which means we can't find any path. If we're moving we should stop movement. //But we won't stop steering; perhaps we'll find a path later. if (mLastSentVelocity.isValid() && mLastSentVelocity != WFMath::Vector<2>::ZERO()) { moveInDirection(WFMath::Vector<2>::ZERO()); } } } }
bool CharacterUpdaterAI::update(const float delta) { if( enabled ) { if( enemy != NULL ) { if( enemy->isActive() == false ) { enemy = NULL; } else { scanForEnemyTimer += delta; if( scanForEnemyTimer > 1.0f ) { scanForEnemyTimer -= scanForEnemyTimer; distanceToEnemy = CCVector3DistanceCheck2D( *player->positionPtr, *enemy->positionPtr ); if( distanceToEnemy < CC_SQUARE( 100.0f ) ) { targetEnemy(); } else if( followingEnemy && distanceToEnemy < CC_SQUARE( 100.0f ) ) { targetEnemy(); } else if( moving == false ) { // Restart tracking if we've stopped moving if( followingEnemy ) { followingEnemy = false; } { if( waypointCycle == cycle_off ) { if( waypointTotal > 0 ) { waypointTotal--; if( waypointTotal > 0 ) { for( int i=0; i<waypointTotal; ++i ) { waypoints[i] = waypoints[i+1]; } goToUsingPath( waypoints[0] ); } } } else { nextWaypoint(); } } } } } } if( shootingState == state_stopped ) { if( followingEnemy ) { if( enemy == NULL ) { followingEnemy = false; } else if( distanceToEnemy < CC_SQUARE( 50.0f ) ) { shoot( *enemy->positionPtr, enemy ); } } } } return super::update( delta ); }
void CharacterUpdaterAI::movePlayer(const float delta) { if( wait > 0.0f ) { player->movementDirection.z = 0.0f; wait -= delta; if( wait <= 0.0f ) { goTo( targetConnection->node->point ); } } else if( moving ) { if( path != NULL ) { super::movePlayer( delta ); } else { const float distance = CCVector3DistanceCheck2D( player->getPosition(), positionTarget, false ); if( distance > 5.0f ) { movePlayerRotation( positionTarget, delta ); } else { if( waypointCycle == cycle_aiNodes && enabled && followingEnemy == false ) { if( pathAnchorNode == NULL || targetConnection == NULL ) { getClosestNode(); pickRandomNode(); } else if( targetConnection->distance > 10.0f || distance < 0.1f ) { pathAnchorNode = targetConnection->node; anchorNode = pathAnchorNode; if( nodesPerMovementCycle++ > 10 ) { int shouldWait = rand() % 5; if( shouldWait == 0 ) { wait = (float)( rand() % 15 ) + 5.0f; } else { movementMagnitude = ( ( rand() % 5 ) * 0.1f ) + 0.3f; } nodesPerMovementCycle = 0; } // Pick a path from that node int randomType = rand() % 5; if( randomType > 1 ) { int closestConnection = 0; float closestAngle = MAXFLOAT; for( int i=0; i<pathAnchorNode->numberOfConnections; ++i ) { const float angleDistance = CCDistanceBetweenAngles( player->rotation.y, pathAnchorNode->connections[i].angle ); if( angleDistance < closestAngle ) { closestConnection = i; closestAngle = angleDistance; } } if( pathAnchorNode->numberOfConnections > 0 ) { targetConnection = &pathAnchorNode->connections[closestConnection]; goTo( targetConnection->node->point ); } else { } } else { pickRandomNode(); } } } else { if( landPlayerOnTarget( distance, delta ) ) { if( enabled && followingEnemy == false ) { if( waypointCycle == cycle_off ) { if( waypointTotal > 0 ) { waypointTotal--; if( waypointTotal > 0 ) { for( int i=0; i<waypointTotal; ++i ) { waypoints[i] = waypoints[i+1]; } goToUsingPath( waypoints[0] ); } } } else { nextWaypoint(); } } } } } } } }