/* * This file is part of UAS2. * * UAS2 is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * UAS2 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with UASv1; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** * @file SimpleAI.cpp * Implements functionality for monster AI. */ #include "SimpleAI.h" #include "MasterServer.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif DWORD SimpleAI::Monsters[MAX_MONSTERS][8]; time_t SimpleAI::NextActionTime; time_t SimpleAI::longtime; /*************** * constructors/destructors **************/ SimpleAI::SimpleAI() { for(DWORD i = 0; i < MAX_MONSTERS; i++) { Monsters[i][0] = 0; // GUID Monsters[i][1] = 0; // Next Action Time Monsters[i][2] = 0; // Action Monsters[i][3] = 0; // Target GUID Monsters[i][4] = 0; // Engaged in Combat Monsters[i][5] = 0; // Is Moving Monsters[i][6] = 0; Monsters[i][7] = 0; } time(&NextActionTime + ACTION_DELAY); } SimpleAI::~SimpleAI() { } void SimpleAI::MoveMonsters( ) { for (int i = 0; i < MAX_MONSTERS; i++) { if ( Monsters[i][5] == 1) { cMonster* pcMonster = (cMonster *) cWorldManager::FindObject( Monsters[i][0] ); cClient* pcClient = cClient::FindClient( pcMonster->m_dwTargetGUID ); if ( pcMonster->m_fHasTarget && pcClient) { pcMonster->m_TargetLocation = pcClient->m_pcAvatar->m_Location; } if (cPhysics::Get3DRange( pcMonster->m_Location, pcMonster->m_TargetLocation ) > 0.07 || !pcMonster->m_fHasTarget ) { cVelocity tarVel = cPhysics::GetTargetVelocity( pcMonster->m_Location, pcMonster->m_TargetLocation ); cLocation newLoc = cPhysics::VelocityMove(pcMonster->m_Location, tarVel, 0.5f); if ( HIWORD(newLoc.m_dwLandBlock) != HIWORD(pcMonster->m_Location.m_dwLandBlock) ) { cWorldManager::MoveRemObject( pcMonster ); pcMonster->m_Location = newLoc; cWorldManager::MoveAddObject( pcMonster ); } else pcMonster->m_Location = newLoc; pcMonster->m_Location.m_flZ = cPhysics::GetLandZ( newLoc ); if ( cPhysics::Get3DRange( pcMonster->m_Location, pcMonster->m_TargetLocation ) < 0.01 ) { SimpleAI::SetMovingComplete( pcMonster->m_dwGUID ); pcMonster->m_fHasTarget = false; cMessage cmPos = pcMonster->SetPosition(); cWorldManager::SendToAllInFocus( pcMonster->m_Location, cmPos, 3 ); pcMonster->m_iPosUpdateCount = 0; } pcMonster->m_iPosUpdateCount++; if (pcMonster->m_iPosUpdateCount >= 4) { cMessage cmPos = pcMonster->SetPosition(); cWorldManager::SendToAllInFocus( pcMonster->m_Location, cmPos, 3 ); pcMonster->m_iPosUpdateCount = 0; } } } } } bool SimpleAI::AddMonster(DWORD dwGUID) { bool fAdded = false; for(int i = 0; i < MAX_MONSTERS; i++) { if(Monsters[i][0] == 0) { time(&longtime); Monsters[i][0] = dwGUID; Monsters[i][1] = longtime + ACTION_DELAY; i = MAX_MONSTERS + 1; fAdded = true; } } return fAdded; } bool SimpleAI::RemoveMonster(DWORD dwGUID) { bool fRemoved = false; for(int i = 0; i < MAX_MONSTERS; i++) { if(Monsters[i][0] == dwGUID) { Monsters[i][0] = 0; Monsters[i][1] = 0; Monsters[i][2] = 0; Monsters[i][3] = 0; Monsters[i][4] = 0; Monsters[i][5] = 0; Monsters[i][6] = 0; Monsters[i][7] = 0; i = MAX_MONSTERS + 1; fRemoved = true; } } return fRemoved; } void SimpleAI::ExecuteActions( ) { for(int i = 0; i < MAX_MONSTERS; i++) { time(&longtime); if((Monsters[i][0] != 0)&&(longtime > Monsters[i][1] )) { srand( timeGetTime( ) ); int iRand = rand( ); iRand = (iRand > 6400) ? iRand % 6400 : iRand; iRand = (iRand < 1600) ? 1600 + iRand : iRand; int delay = iRand/100; Monsters[i][1] = longtime + delay; cObject* pcObject = cWorldManager::FindObject( Monsters[i][0] ); if(pcObject) { cMonsterServer::ProcessAction(Monsters[i][0],Monsters[i][2], Monsters[i][4], Monsters[i][3]); } else { //Nothing to do } } } } void SimpleAI::SetAction( DWORD dwGUID, DWORD dwEvent, WORD wDelay ) { for(int i = 0; i < MAX_MONSTERS; i++) { if(Monsters[i][0] == dwGUID) { Monsters[i][1] = longtime + wDelay; Monsters[i][2] = dwEvent; Monsters[i][3] = 0; i = MAX_MONSTERS + 1; } } } void SimpleAI::SetMoving( DWORD dwGUID ) { for (int i=0; i < MAX_MONSTERS; i++) { if ( Monsters[i][0] == dwGUID ) { Monsters[i][5] = 1; i = MAX_MONSTERS + 1; } } } void SimpleAI::SetMovingComplete( DWORD dwGUID ) { for (int i=0; i < MAX_MONSTERS; i++) { if ( Monsters[i][0] == dwGUID ) { Monsters[i][5] = 0; i = MAX_MONSTERS + 1; } } } void SimpleAI::SetUnderAttack( DWORD dwGUID, DWORD dwTarget ) { for(int i = 0; i < MAX_MONSTERS; i++) { if(Monsters[i][0] == dwGUID) { if(Monsters[i][4] == 1) { Monsters[i][1] = longtime + 0; Monsters[i][2] = 5; //Monsters[i][3] = dwTarget; Monsters[i][4] = 1; // Engaged in Combat } else { Monsters[i][1] = longtime + 0; Monsters[i][2] = 1; Monsters[i][3] = dwTarget; Monsters[i][4] = 1; // Engaged in Combat } i = MAX_MONSTERS + 1; } } } void SimpleAI::SetAttackComplete( DWORD dwGUID ) { for(int i = 0; i < MAX_MONSTERS; i++) { if(Monsters[i][0] == dwGUID) { Monsters[i][1] = longtime + 1; Monsters[i][2] = 7; Monsters[i][3] = 0; Monsters[i][4] = 0; // Dis-Engaged from Combat i = MAX_MONSTERS + 1; } } } void SimpleAI::SetAttackEvent( DWORD dwGUID, DWORD dwTarget, DWORD dwEvent, WORD wDelay ) { for(int i = 0; i < MAX_MONSTERS; i++) { if(Monsters[i][0] == dwGUID) { Monsters[i][1] = longtime + wDelay; Monsters[i][2] = dwEvent; Monsters[i][3] = dwTarget; i = MAX_MONSTERS + 1; } } } void SimpleAI::SetTargetKilled( DWORD dwTarget ) { for(int i = 0; i < MAX_MONSTERS; i++) { if(Monsters[i][3] == dwTarget) { Monsters[i][1] = 5; Monsters[i][2] = 0; Monsters[i][3] = 0; Monsters[i][4] = 0; // Disengaged from combat } } }