/* * 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 Objects.cpp * Implements general functionality for all objects. * All object types inherit from this class. */ #include "Client.h" #include "DatFile.h" #include "Object.h" #include "WorldManager.h" #include void cObject::SetLocation( double dNS, double dEW ) { DWORD dwNewLandBlock; m_Location.m_flX = ( dEW * 10.0f + 1020.0f ) * 24.0f; m_Location.m_flY = ( dNS * 10.0f - 1020.0f ) * 24.0f; m_Location.m_flZ = 500.0f; dwNewLandBlock = ( (BYTE) ((((DWORD)m_Location.m_flX % 192) / 24.0f) * 8.0f) + ( ((DWORD)m_Location.m_flY % 192) / 24) ) | ( (0x00) << 8) | ( (BYTE) (m_Location.m_flY / 192.0f) << 16) | ( (BYTE) (m_Location.m_flX / 192.0f) << 24); dwNewLandBlock -= 0x00010000; m_Location.m_flX = (float)((int) m_Location.m_flX % 192); m_Location.m_flY = (float)((int) m_Location.m_flY % 192); m_Location.m_dwLandBlock = dwNewLandBlock; } void cObject::ReSpawn( cObject *pcObject ) { } cMessage cObject::Animation( WORD wAnim, float flPlaySpeed ) { cMessage cAnim; WORD wAnimPart2; static BYTE Canimation[] = { 0x4C, 0xF7, 0x00, 0x00, 0x56, 0x1F, 0x05, 0x50, 0x3C, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x80, 0xF0, 0xD0, 0x03, 0x7C, 0x00, 0x01, 0x00, 0xCA, 0x3F, 0x00, 0x00,//0x00, 0x00, 0x80, 0x3F, }; ++m_wCurAnim; CopyMemory( &Canimation[04], &m_dwGUID, 4 ); CopyMemory( &Canimation[8], &m_wNumLogins, 2 ); CopyMemory( &Canimation[10], &m_wCurAnim, 2 ); CopyMemory( &Canimation[12], &++m_wMeleeSequence, 2 ); CopyMemory( &Canimation[24], &wAnim, 2 ); CopyMemory( &Canimation[28], &flPlaySpeed, 4 ); wAnimPart2 = m_wCurAnim - 6; CopyMemory( &Canimation[26], &wAnimPart2, 2 ); cAnim.CannedData( Canimation, sizeof( Canimation ) ); return cAnim; } cMessage cObject::Animation( WORD wAnim, float flPlaySpeed, BYTE bActivity ) { cMessage cAnim; WORD wAnimPart2; static BYTE Canimation[] = { 0x4C, 0xF7, 0x00, 0x00, 0x56, 0x1F, 0x05, 0x50, 0x3C, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x80, 0xF0, 0xD0, 0x03, 0x7C, 0x00, 0x01, 0x00, 0xCA, 0x3F, 0x00, 0x00,//0x00, 0x00, 0x80, 0x3F, }; ++m_wCurAnim; CopyMemory( &Canimation[04], &m_dwGUID, 4 ); CopyMemory( &Canimation[8], &m_wNumLogins, 2 ); CopyMemory( &Canimation[10], &m_wCurAnim, 2 ); CopyMemory( &Canimation[12], &++m_wMeleeSequence, 2 ); CopyMemory( &Canimation[24], &wAnim, 2 ); CopyMemory( &Canimation[28], &flPlaySpeed, 4 ); wAnimPart2 = m_wCurAnim - 6; CopyMemory( &Canimation[26], &wAnimPart2, 2 ); cAnim.CannedData( Canimation, sizeof( Canimation ) ); return cAnim; } void cObject::Attack(cClient *pcAttacker, float flDamageSlider, DWORD F7B0Sequence ) { } void cObject::SpellAttack(cClient *pcAttacker, cObject *pcWarSpell, DWORD F7B0Sequence ) { } cMessage cObject::RemoveObj( DWORD dwGUID ) { cMessage cmRemove; cmRemove << 0xF747L << dwGUID << 0x0L ; return cmRemove; } cMessage cObject::AdjustBar( DWORD dwGUID, DWORD F7B0Sequence ) { cMessage cmHealth; cmHealth << 0xF7B0L << dwGUID << F7B0Sequence << 0x01C0L << m_dwGUID << 1.0f; return cmHealth; } cMessage cObject::LocationPacket( ) { WORD wInvSeq = (WORD(m_bInventorySequence) * 5) - 1; cMessage cmPacket; cmPacket << 0xF748L << m_dwGUID << 0x34L << m_Location.m_dwLandBlock << m_Location.m_flX << m_Location.m_flY << m_Location.m_flZ << m_Location.m_flA << m_Location.m_flB << m_wNumLogins << WORD( wInvSeq ) << WORD( ++m_wPositionSequence ) << WORD( 0 ); return cmPacket; } cMessage cObject::CombatAnimation( DWORD dwTarget, WORD wAttackAnim ) { cMessage cmRet; unsigned char Canimation [] = { 0x4C, 0xF7, 0x00, 0x00, 0xE6, 0xD2, 0x09, 0x50, // object 0x3C, 0x00, 0x18, 0x00, // numLogins, sequence 0x03, 0x00, 0x00, 0x00, // numAnims, activity 0x00, 0x01, 0x00, 0x00, // Anim type, type flag 0xC1, 0x80, 0x99, 0xB1, 0x63, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x01, 0x00, 0xE4, 0x38, 0x8E, 0x3F, 0x00, 0x00, 0x20, 0x8B, 0x99, 0xB1, // dwTarget }; CopyMemory(&Canimation[4],&m_dwGUID,4); CopyMemory( &Canimation[8], &m_wNumLogins, 2 ); m_wCurAnim++; CopyMemory(&Canimation[10],&m_wCurAnim,2); m_wMeleeSequence++; CopyMemory(&Canimation[12],&m_wMeleeSequence,2); CopyMemory(&Canimation[0x28],&dwTarget,4); CopyMemory(&Canimation[0x20],&m_wCurAnim,2); CopyMemory(&Canimation[24],&wAttackAnim,2); cmRet.pasteData(Canimation,sizeof(Canimation)); return cmRet; } cMessage cObject::ChangeCombatMode( bool fMode) { cMessage cmReturn; cmReturn << 0xFF00; return cmReturn; } /** * Handles the message sent for the creation of an object in the world. * * This function is called whenever an object should be created in the world for a client. * @return cMessage - Returns a Create Object (0x0000F745) server message. */ cMessage cAbiotic::CreatePacket( ) { cMessage cmCreate; cmCreate << 0xF745L << m_dwGUID << BYTE( 0x11 ) << BYTE( 0 ) << BYTE( 0 ) << BYTE( 0 ); DWORD dwFlags = 0x00001881; if ( !m_fIsOwned ) dwFlags |= 0x8000; cmCreate << dwFlags; if( m_fIsSolid ) cmCreate << DWORD( 0x00000008 ); else cmCreate << DWORD( 0x00010044 ); if ( !m_fIsOwned ) cmCreate.CannedData( (BYTE *)&m_Location, sizeof( cLocation ) ); cmCreate << 0x20000014L << 0x3400002BL; DWORD dwModel = 0x02000000L + m_dwModel; cmCreate << dwModel << m_flScale; // SeaGreens WORD wUnkFlag2 = 0x1; WORD wUnkFlag3 = 0x1; WORD wUnkFlag4 = 0; WORD wUnkFlag6 = 0; WORD wUnkFlag7 = 0; WORD wUnkFlag8 = 0; WORD wUnkFlag10 = 0; cmCreate << m_wPositionSequence << wUnkFlag2 << wUnkFlag3 << wUnkFlag4 << m_wNumPortals << wUnkFlag6 << wUnkFlag7 << wUnkFlag8 << m_wNumLogins << wUnkFlag10; DWORD dwFlags2 = 0x00000218; if ( m_fIsOwned ) dwFlags2 |= 0x4000; cmCreate << dwFlags2 << m_strName.c_str( ) << WORD( 0x013A ) << WORD( m_wIcon ); DWORD dwObjectFlags1 = 0x01; cmCreate << dwObjectFlags1; DWORD dwObjectFlags2 = 0x00; if ( m_fSelectable ) dwObjectFlags2 |= 0x10; else dwObjectFlags2 |= 0x80; if ( !m_fEquippable ) dwObjectFlags2 |= 0x04; // Uncommented Blackstaff 04/13/02 else dwObjectFlags2 |= 0x00; //dwObjectFlags2 |= 0x10000 | 0x20000 | 0x40000; cmCreate << dwObjectFlags2 << m_dwValue << m_dwValue;// << 0x00100000 << 0x00100000 << 0x00100000; BYTE bEquipType = 0x01; cmCreate << bEquipType; if ( m_fIsOwned ) cmCreate << m_dwContainer; return cmCreate; } /** * Handles the assessment of objects. * * This function is called whenever an objects is assessed by a client. * Returns a Game Event (0x0000F7B0) server message of type Identify Object (0x000000C9). */ void cAbiotic::Assess( cClient *pcAssesser ) { cMessage cmAssess; cmAssess << 0xF7B0L << pcAssesser->m_pcAvatar->GetGUID() << ++pcAssesser->m_dwF7B0Sequence << 0xC9L; cmAssess << m_dwGUID << 0x00000800L << 1L << 1L << m_dwValue << m_dwWeight; pcAssesser->AddPacket( WORLD_SERVER, cmAssess, 4 ); cMessage cmActionComplete; cmActionComplete << 0xF7B0L << pcAssesser->m_pcAvatar->GetGUID( ) << ++pcAssesser->m_dwF7B0Sequence << 0x01C7L << 0L << 0L; pcAssesser->AddPacket(WORLD_SERVER,cmActionComplete,4); } DWORD cObject::CalculateDamage(int strength, float flPower, float flResistance ) { srand( timeGetTime( ) ); int iRand = rand( ); iRand = (iRand > 6400) ? iRand % 6400 : iRand; iRand = (iRand < 1600) ? 1600 + iRand : iRand; double dLuckFactor = 3200.0f / (double)iRand; // MaxDamage = (Strength * 0.2 * (flPower + 1.15)) / (flResistance + 5.0) double dMaxDamage = (double)((strength * 0.2f) * ((flPower + .25f) * 4)) / (double)(flResistance + 7.5f); return dMaxDamage * dLuckFactor + (rand( ) % 2); } cMessage cObject::TurnToTarget( float flHeading, DWORD dwTargetGUID ) { cMessage cmTurnToTarget; cmTurnToTarget << 0xF74CL << m_dwGUID << m_wNumLogins << ++m_wCurAnim << ++m_wMeleeSequence << WORD(0x0000) << BYTE(0x08) << BYTE(0x00) << WORD(0x003D) << dwTargetGUID << flHeading << 0x1139EE0F << 1.0f << 0x00000000; return cmTurnToTarget; } float cObject::GetRange( DWORD dwTargetLandblock, float flTarX, float flTarY, float flTarZ ) { float nsCoord,ewCoord; float nsTarCoord,ewTarCoord; float flRange; lb LocLB, TarLB; CopyMemory( &LocLB,&m_Location.m_dwLandBlock , 4 ); CopyMemory( &TarLB,&dwTargetLandblock , 4 ); nsCoord = ( ( ( ( LocLB.bLo + 1 ) * 8 ) + ( m_Location.m_flY / 24 ) ) - 1027.5 )/10; ewCoord = ( ( ( ( LocLB.bHi + 1 ) * 8 ) + ( m_Location.m_flX / 24 ) ) - 1027.5 )/10; nsTarCoord = ( ( ( ( TarLB.bLo + 1 ) * 8 ) + ( flTarY / 24 ) ) - 1027.5 )/10; ewTarCoord = ( ( ( ( TarLB.bHi + 1 ) * 8 ) + ( flTarX / 24 ) ) - 1027.5 )/10; flRange = sqrt(pow(nsTarCoord - nsCoord,2) + pow(ewTarCoord - ewCoord,2))*10; return flRange; } float cObject::GetHeadingTarget( DWORD dwTargetLandblock, float flTarX, float flTarY, float flTarZ ) { float nsCoord,ewCoord; float nsTarCoord,ewTarCoord; float flHeading; float intRange; lb LocLB, TarLB; flHeading = 0.0f; CopyMemory( &LocLB,&m_Location.m_dwLandBlock , 4 ); CopyMemory( &TarLB,&dwTargetLandblock , 4 ); /* nsCoord = ( ( ( ( LocLB.bLo + 1 ) * 8 ) + ( flY / 24 ) ) - 1027.5 )/10; ewCoord = ( ( ( ( LocLB.bHi + 1 ) * 8 ) + ( flX / 24 ) ) - 1027.5 )/10; nsTarCoord = ( ( ( ( TarLB.bLo + 1 ) * 8 ) + ( flTarY / 24 ) ) - 1027.5 )/10; ewTarCoord = ( ( ( ( TarLB.bHi + 1 ) * 8 ) + ( flTarX / 24 ) ) - 1027.5 )/10; */ nsCoord = (((((m_Location.m_dwLandBlock & 0x00FF0000) / 0x0010000) & 0xFF) + 1) * 8) + static_cast(m_Location.m_flY / 24) - 1027.5; ewCoord = (((((m_Location.m_dwLandBlock & 0xFF000000) / 0x1000000) & 0xFF) + 1) * 8) + static_cast(m_Location.m_flX / 24) - 1027.5; nsTarCoord = (((((dwTargetLandblock & 0x00FF0000) / 0x0010000) & 0xFF) + 1) * 8) + static_cast(flTarY / 24) - 1027.5; ewTarCoord = (((((dwTargetLandblock & 0xFF000000) / 0x1000000) & 0xFF) + 1) * 8) + static_cast(flTarX / 24) - 1027.5; intRange = sqrt(pow(nsTarCoord - nsCoord,2) + pow(ewTarCoord - ewCoord,2)); if(intRange > 0) { if(nsTarCoord - nsCoord < 0 ) { flHeading = acos((ewTarCoord - ewCoord) / intRange) * 57.2957796; } else { flHeading = acos(-(ewTarCoord - ewCoord) / intRange) * 57.2957796 + 180; } } return flHeading + 90; } cMessage cObject::MoveToTarget( cClient *pcWho ) { // pcWho is the target client cMessage cmMoveToTarget; float flHeadingTarget; DWORD dwFlags; dwFlags = 0x1279EFF0; flHeadingTarget = GetHeadingTarget( pcWho->m_pcAvatar->m_Location.m_dwLandBlock,pcWho->m_pcAvatar->m_Location.m_flX,pcWho->m_pcAvatar->m_Location.m_flY,pcWho->m_pcAvatar->m_Location.m_flZ); // Positional Info only cmMoveToTarget << 0xF74CL // dword 1 << m_dwGUID // dword 2 << m_wNumLogins // word << ++m_wCurAnim // + word = dword 3 << ++m_wMeleeSequence // word << WORD(0x0000) // + word = dword 4 << BYTE(0x06) // byte << BYTE(0x00) // +byte << WORD(0x003E); // +word = dword 5 // Who/Where we are Moving to cmMoveToTarget << pcWho->m_pcAvatar->GetGUID( ) // dword 6 << m_Location.m_dwLandBlock//pcWho->m_pcAvatar->m_Location.m_dwLandBlock // dword 7 << m_Location.m_flX//pcWho->m_pcAvatar->m_Location.m_flX // dword 8 << m_Location.m_flY//pcWho->m_pcAvatar->m_Location.m_flY // dword 9 << m_Location.m_flZ//pcWho->m_pcAvatar->m_Location.m_flZ // dword 10 << dwFlags // dword 11 - does not change << flHeadingTarget // dowrd 12 << 0.1f // dword 13 - does not change //pcWho->m_pcAvatar->m_Location.m_flC << 15.0f // dword 14 - Run speed value << 1.5f // dword 15 << 15.0f // dword 16 << 0x0L // dword 17 << 1.8201754f; // dword 18 //SetLocation(&pcWho->m_pcAvatar->m_Location); return cmMoveToTarget; } ////////////////////// cMessage cObject::MoveTarget( cClient *pcWho ) { // pcWho is the target client cMessage cmMoveToTarget; float flHeadingTarget; DWORD dwFlags; dwFlags = 0x1279EFF0; flHeadingTarget = GetHeadingTarget( pcWho->m_pcAvatar->m_Location.m_dwLandBlock,pcWho->m_pcAvatar->m_Location.m_flX,pcWho->m_pcAvatar->m_Location.m_flY,pcWho->m_pcAvatar->m_Location.m_flZ); cmMoveToTarget << 0xF74CL << m_dwGUID << m_wNumLogins << ++m_wCurAnim << ++m_wMeleeSequence << WORD(0x0000) << BYTE(0x06) << BYTE(0x00) << WORD(0x003E); cmMoveToTarget << pcWho->m_pcAvatar->GetGUID( ) << pcWho->m_pcAvatar->m_Location.m_dwLandBlock << pcWho->m_pcAvatar->m_Location.m_flX << pcWho->m_pcAvatar->m_Location.m_flY << pcWho->m_pcAvatar->m_Location.m_flZ << dwFlags << 0.0f << 0.1f << 75.0f << 1.0f << 15.0f << flHeadingTarget << 1.8201754f; SetLocation(&pcWho->m_pcAvatar->m_Location); return cmMoveToTarget; } //////////////////////////////////////////// // Never Use this function //////////////////////////////////////////// cMessage cObject::ReturnToSpawn( ) { cMessage cmReturnToSpawn; float flHeadingTarget = 0.0f; DWORD dwFlags; float flDistance = 1.0f; cLocation tempLoc; dwFlags = 0x1291EE0F; flHeadingTarget = GetHeadingTarget( m_SpawnLoc.m_dwLandBlock,m_SpawnLoc.m_flX,m_SpawnLoc.m_flY,m_SpawnLoc.m_flZ); flDistance = GetRange( m_SpawnLoc.m_dwLandBlock, m_SpawnLoc.m_flX, m_SpawnLoc.m_flY, m_SpawnLoc.m_flZ ); tempLoc = EstimateLoc(flHeadingTarget,10,flDistance,2.0f); cmReturnToSpawn << 0xF74CL << m_dwGUID << m_wNumLogins << ++m_wCurAnim << ++m_wMeleeSequence << WORD(0x0000) << BYTE(0x07) << BYTE(0x00) << WORD(0x003D); // Animation Type 0x07 cmReturnToSpawn << tempLoc.m_dwLandBlock << tempLoc.m_flX << tempLoc.m_flY << tempLoc.m_flZ << dwFlags << 0.0f//flHeadingTarget << 1.0f << DWORD(0x7F7FFFFF) << 1.0f << 5.0f << flHeadingTarget << 1.6346154f; return cmReturnToSpawn; } /////////////////////////////////////////////////////////////////////////// // CoordLoc - Converts NS/EW map coordinates into Landblock Data form // // /////////////////////////////////////////////////////////////////////////// cLocation cObject::CoordLoc( float dNS, float dEW ) { cLocation Loc; char tmpLB[5]; struct{ BYTE bHi; BYTE bLo; BYTE bOO; BYTE bLow; } lb; Loc.m_flX = ((dEW * 10.0f) + 1027.5f ) * 24.0f; Loc.m_flY = ((dNS * 10.0f) + 1027.5f ) * 24.0f; Loc.m_flZ = 0.0f;//500.0f; Loc.m_flX = ( float )( ( DWORD ) Loc.m_flX % 192); Loc.m_flY = ( float )( ( DWORD ) Loc.m_flY % 192); sprintf(tmpLB," \r\n"); lb.bHi = ((((dEW*10)+1027.5)-(Loc.m_flX/24))/8); lb.bLo = ((((dNS*10)+1027.5)-(Loc.m_flY/24))/8)-1; lb.bOO = 0x00; // Indicates on Surface map 0x01 indicates in Dungeon lb.bLow = ((Loc.m_flX/24)*8) + (Loc.m_flY/24); CopyMemory( &tmpLB[3], &lb.bHi, 1 ); CopyMemory( &tmpLB[2], &lb.bLo, 1 ); CopyMemory( &tmpLB[1], &lb.bOO, 1 ); CopyMemory( &tmpLB[0], &lb.bLow, 1 ); CopyMemory( &Loc.m_dwLandBlock, &tmpLB, 4 ); return Loc; } cLocation cObject::EstimateLoc( float flHeading, float flSpeed, float flDistToTarget, float flTime ) { cLocation Loc; lb LocLB,NewLB; float flEndX = 1.0f; float flEndY = 1.0f; float flRadHeading = 0.0f; float flDistance = 1.0f; float dNS, dEW; if(flSpeed < 10.0f) { flSpeed = 10.0f; } flDistance = (flSpeed*flTime); if( flDistToTarget < 0.5f) { flDistance = flDistToTarget/4; } flRadHeading = ((flHeading * 3.14159265359)/180); CopyMemory( &LocLB,&m_Location.m_dwLandBlock , 4 ); //dNS2 = ( ( ( ( LocLB.bLo + 1 ) * 8 ) + ( flY / 24 ) ) - 1027.5 )/10; //dEW2 = ( ( ( ( LocLB.bHi + 1 ) * 8 ) + ( flX / 24 ) ) - 1027.5 )/10; flEndX = (float)(flDistance * sin(flRadHeading)); flEndY = (float)(flDistance * cos(flRadHeading)); dNS = (float)(m_Location.m_flY + flEndY); dEW = (float)(m_Location.m_flX + flEndX); // set Landblock HI (EW movement) if(dNS > 193) { NewLB.bLo = LocLB.bLo + 1; dNS = dNS - 193; } else if (dNS < 0) { NewLB.bLo = LocLB.bLo - 1; dNS = dNS + 193; } else { NewLB.bLo = LocLB.bLo; } // Set Landblock LO (NS movement) if(dEW > 193) { NewLB.bHi = LocLB.bHi + 1; dEW = dEW - 193; } else if(dEW < 0) { NewLB.bHi = LocLB.bHi - 1; dEW = dEW + 193; } else { NewLB.bHi = LocLB.bHi; } Loc.m_flX = dEW; Loc.m_flY = dNS; Loc.m_flZ = 0.0f; NewLB.bOO = 0x00; // Indicates on Surface map 0x01 indicates in Dungeon NewLB.bLow = ((dEW/24)*8) + (dNS/24); CopyMemory( &Loc.m_dwLandBlock,&NewLB , 4 ); return Loc; } cMessage cObject::SetPosition() { cMessage cmSetPosition; DWORD dwFlags = 0x34L; cmSetPosition << 0xF748L << m_dwGUID << 0x34L; cmSetPosition << m_Location.m_dwLandBlock << m_Location.m_flX << m_Location.m_flY << m_Location.m_flZ << m_Location.m_flA << m_Location.m_flB << m_Location.m_flC << m_Location.m_flW; return cmSetPosition; }