/* * 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 WarSpell.cpp */ #include "Object.h" #include "WorldManager.h" #include "Job.h" #include "CorpseCleaner.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif /** * Angle "val" is converted to (160 index), which corresponds to the ring of 16 sonar. * This index value is then returned. * Units are 1/10 degrees and 160 index (1/10th of 16). */ int deg_to_index_160(int val) { int idx; idx = val * 2 / 45; /* (idx = val/22.5) */ if (idx < 0) idx += 160; return(idx); } /********** * methods *********/ /** * Handles the message sent for the creation of war spells. * * This function is called whenever a war spells should be created for a client. * @return cMessage - Returns a Create Object (0x0000F745) server message. */ cMessage cWarSpell::CreatePacket() { cMessage cmReturn; cMagicModels *pcModel = cMagicModels::FindModel( m_dwSpellModel ); if( pcModel ) { float flpScale = 0.5f; // Scale used in Packet being Sent cmReturn << 0xF745L << m_dwGUID << BYTE(0x11); //0x11 is a constant cmReturn << BYTE(0x0) << BYTE(0x0) << BYTE(0x0); DWORD dwFlags1 = pcModel->m_dwFlags1;// 0x0000FB85; // Flags 1 defines whats next cmReturn << dwFlags1; cmReturn << WORD(0x8B48); // Type of portal cmReturn << WORD(0x0002); // Unknown //Flags1 Mask 0x0000FB85 { //Flags1 & 0x00008000 Location { //m_Location.m_flZ = m_Location.m_flZ + 1.4f; cmReturn.pasteData( (UCHAR*)&m_Location, sizeof(m_Location) ); //Next comes the location } //Flags1 & 0x00000800 { //SoundConfig cmReturn << 0x20000000 + pcModel->m_wSoundSet;//0x20000039; } //Flags1 & 0x00001000 { //Unknown_Blue // Particle Effect for spell cmReturn << 0x34000000 + pcModel->m_wParticle; //0x3400000B; } //Flags1 & 0x00000001 { //DWORD dwModel = 0x02000001; //the model. cmReturn << 0x02000000 + pcModel->m_dwModelNumber;//0x020003F6; } //Flags1 & 0x00000080 unknown_green { //FLOAT flpScale cmReturn << pcModel->m_flScale; } //Flags1 & 0x00000100 { //Unkown_darkbrown cmReturn << 1.0f;//0x3F800000; } //Flags1 & 0x00000200 { //Unknown_BrightPurple cmReturn << 0x00000000; } //Flags1 & 0x00000004 { //Velocity Vector float flSpeed = 10; char Command2[100]; sprintf(Command2,"dx: %f dy: %f dz: %f Speed: %f\r\n", m_Velocity.m_dx, m_Velocity.m_dy, m_Velocity.m_dz, flSpeed); //UpdateConsole(Command2); cmReturn << (m_Velocity.m_dx*flSpeed); cmReturn << (m_Velocity.m_dy*flSpeed); cmReturn << (m_Velocity.m_dz*flSpeed); } //Flags1 & 0x00002000 { // cmReturn << 0x00000059; } //Flags1 & 0x00004000 { // cmReturn << 0x3F800000; } } // SeaGreens WORD wUnkFlag2 = 0x0000; WORD wUnkFlag3 = 0x0000; WORD wUnkFlag4 = 0x0001; WORD wUnkFlag6 = 0x0000; WORD wUnkFlag7 = 0x0000; WORD wUnkFlag8 = 0x0000; WORD wUnkFlag10 = 0x0000; cmReturn << m_wPositionSequence //movement 0x0001 << wUnkFlag2 // animations << wUnkFlag3 // bubble modes << wUnkFlag4 //num jumps << m_wNumPortals << wUnkFlag6 //anim count << wUnkFlag7 // overrides << wUnkFlag8 << m_wNumLogins // 0x0D4B << wUnkFlag10; DWORD dwFlags2 = 0x00400000; //Flags2 Defines what data comes next cmReturn << dwFlags2; cmReturn << pcModel->m_strName;//Name( ); // Object's Name cmReturn << WORD(pcModel->m_wModel) << WORD(pcModel->m_wIcon); //m_wModelID << m_wIconID; DWORD dwObjectFlags1 = 0x00000000; // 0x0000 Nothing DWORD dwObjectFlags2 = 0x00000094; // 0x0004 Can not be picked up, 0x0080 Unknown - Can not be selected 0x0010 Unknown - Can be selected. // appears to contradict it self sets Can not be Selected and Can be Selected. Housing Item, may set house open/closed cmReturn << dwObjectFlags1 << dwObjectFlags2; //Flags2 Mask { // 0x00400000 Word Associated Spell { WORD wUnknown9 = pcModel->m_wAssociatedSpell;//0x3A; cmReturn << wUnknown9; } } //cmReturn << WORD(0x0000); } else { UpdateConsole(" Spell Error! %d\r\n", m_dwSpellModel); } return cmReturn; } /** * Handles the movement of war spells. * * This function is called whenever a war spell's position should be updated. */ int cWarSpell::Move( LPVOID wp, LPVOID lp ) { cSpellMoveParam* SpellMoveParam = (cSpellMoveParam *) wp; cWarSpell *pcWarSpell = (cWarSpell*) cWorldManager::FindObject( SpellMoveParam->GetWarSpellGUID() ); cClient *pcClient = cClient::FindClient( SpellMoveParam->GetCasterGUID() ); cLocation newLoc = cPhysics::VelocityMove(pcWarSpell->m_Location, pcWarSpell->m_Velocity, 1.0f); if ( HIWORD(newLoc.m_dwLandBlock) != HIWORD(pcWarSpell->m_Location.m_dwLandBlock) ) { cWorldManager::MoveRemObject( pcWarSpell ); pcWarSpell->m_Location = newLoc; cWorldManager::MoveAddObject( pcWarSpell ); } else pcWarSpell->m_Location = newLoc; char Command[100]; sprintf(Command,"Move! X: %f Y: %f\r\n", pcWarSpell->m_Location.m_flX, pcWarSpell->m_Location.m_flY); //UpdateConsole(Command); if ( cMonster *CollisionMonster = (cMonster*) cWorldManager::GetCollisionMonster( pcWarSpell->GetGUID(), pcWarSpell->m_Location ) ) { //UpdateConsole(" Hit!\r\n"); cMessage msgImpact = pcWarSpell->SpellImpact(pcWarSpell,0x0005,1.0f); cWorldManager::SendToAllInFocus( pcWarSpell->m_Location, msgImpact, 3 ); cMessage msgVis = pcWarSpell->SpellVis(pcWarSpell); cWorldManager::SendToAllInFocus( pcWarSpell->m_Location, msgVis, 3 ); CollisionMonster->SpellAttack( pcClient , pcWarSpell, ++pcClient->m_dwF7B0Sequence); SimpleAI::SetUnderAttack( CollisionMonster->GetGUID(), pcClient->m_pcAvatar->GetGUID() ); CorpseCleaner::AddCorpse(pcWarSpell->GetGUID(),2); SAFEDELETE( SpellMoveParam ) return 2; } else if ( pcWarSpell->m_Location.m_flZ < cPhysics::GetLandZ( pcWarSpell->m_Location ) ) { //UpdateConsole(" Land hit!\r\n"); cMessage msgImpact = pcWarSpell->SpellImpact(pcWarSpell,0x0005,1.0f); cWorldManager::SendToAllInFocus( pcWarSpell->m_Location, msgImpact, 3 ); cMessage msgVis = pcWarSpell->SpellVis(pcWarSpell); cWorldManager::SendToAllInFocus( pcWarSpell->m_Location, msgVis, 3 ); CorpseCleaner::AddCorpse(pcWarSpell->GetGUID(),2); SAFEDELETE( SpellMoveParam ) return 2; } if ( cPhysics::Get3DRange( SpellMoveParam->GetCastLocation(), pcWarSpell->m_Location ) > 3.3333 ) { UpdateConsole(" Dissipate.\r\n"); CorpseCleaner::AddCorpse(pcWarSpell->GetGUID(),2); SAFEDELETE( SpellMoveParam ) return 2; } cMessage msgSpellPosition = pcWarSpell->SetPosition(); //cWorldManager::SendToAllInFocus( pcWarSpell->m_Location, msgSpellPosition, 3 ); return -1; } /** * Handles the general actions of war spell objects. */ void cWarSpell::Action(cClient *who) { } /** * Handles the assessment of war spell objects. This should not be called. */ void cWarSpell::Assess(cClient *pcAssesser) { } /** * Particle effects for war spell objects. * * This function is called when a war spell should display a particle effect. * @return cMessage - Returns an Apply Visual/Sound Effect (0x0000F755) server message. */ cMessage cWarSpell::WarParticle(cWarSpell* pcWarSpell,DWORD dwEffect,float flSpeed) { cMessage cmWarParticle; static BYTE cbApplyEffect[] = { 0x55, 0xF7, 0x00, 0x00, 0xBA, 0x2E, 0xC5, 0xC2, 0x04, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, }; CopyMemory( &cbApplyEffect[4], &pcWarSpell->m_dwGUID, 4 ); CopyMemory( &cbApplyEffect[8], &dwEffect, 4 ); CopyMemory( &cbApplyEffect[12], &flSpeed, 4 ); cmWarParticle.CannedData( cbApplyEffect, sizeof( cbApplyEffect ) ); return cmWarParticle; } /** * Impact effects for war spell objects. * * This function is called when a war spell should display an impact effect. * @return cMessage - Returns an Apply Visual/Sound Effect (0x0000F755) server message. */ cMessage cWarSpell::SpellImpact(cWarSpell* pcWarSpell, DWORD dwEffect, float flSpeed) { cMessage cmSpellImpact; static BYTE cbApplyImpact[] = { 0x55, 0xF7, 0x00, 0x00, 0xBA, 0x2E, 0xC5, 0xC2, 0x04, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, }; CopyMemory( &cbApplyImpact[4], &pcWarSpell->m_dwGUID, 4 ); CopyMemory( &cbApplyImpact[8], &dwEffect, 4 ); CopyMemory( &cbApplyImpact[12], &flSpeed, 4 ); cmSpellImpact.CannedData( cbApplyImpact, sizeof( cbApplyImpact ) ); return cmSpellImpact; } /** * Toggles war spell visibility. * * This function is called when the visibility of a war spell should change for a client. * @return cMessage - Returns a Toggle Object Visibility (0x0000F74B) server message. */ cMessage cWarSpell::SpellVis(cWarSpell* pcWarSpell) { cMessage cmSpellVis; static BYTE cbApplyVis[] = { 0x4B, 0xF7, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x74, 0x83, //Portal type 0x12, 0x00, //Unknown word 0x06, 0x00, //NumLogins 0x01, 0x00, //NumPortals 0x43, 0x3D, 0x09, 0x01, }; CopyMemory( &cbApplyVis[4], &pcWarSpell->m_dwGUID, 4 ); cmSpellVis.CannedData( cbApplyVis, sizeof( cbApplyVis ) ); return cmSpellVis; } /** * Sends a war spell animation. * * This function is called when an animation for a war spell should sent to a client. * @return cMessage - Returns a Set Animation (0x0000F74C) server message. */ cMessage cWarSpell::SpellAnim(cWarSpell* pcWarSpell,WORD wWarAnim,WORD wWarAnim2) { cMessage cmSpellAnim; static BYTE cbSpellAnim[] = { 0x4C, 0xF7, 0x00, 0x00, 0xBA, 0x31, 0xC5, 0xC2, //GUID 0x01, 0x00, //numLogins 0x03, 0x00, //sequence 0x03, 0x00, //numAnim 0x00, 0x00, //activity 0x00, 0x00, //animation Type 0x3C, 0x00, //Stance 0x01, 0xF0, 0x99, 0x02, //flags 0x3C, 0x00, 0x00, 0x00, //stanceMode2 0x3F, 0x80, 0x00, 0x00, }; CopyMemory( &cbSpellAnim[4], &pcWarSpell->m_dwGUID, 4 ); CopyMemory( &cbSpellAnim[18], &wWarAnim, 2 ); CopyMemory( &cbSpellAnim[24], &wWarAnim2, 2 ); cmSpellAnim.pasteData( cbSpellAnim, sizeof( cbSpellAnim ) ); return cmSpellAnim; } /** * Sets the location for war spell objects. * * This function is called whenever the location of a war spell should be updated for a client. * @return cMessage - Returns a Set Position and Motion (0x0000F748) server message. */ cMessage cWarSpell::SetPosition() { cMessage cmSetPosition; DWORD dwFlags = 0x01L; cmSetPosition << 0xF748L << m_dwGUID << 0x01L; 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 << m_Velocity.m_dx << m_Velocity.m_dy << m_Velocity.m_dz; return cmSetPosition; }