diff --git a/.gitignore b/.gitignore index aacadd7..9a2ab7c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,11 +3,29 @@ build-*/ .env # Windows game client + data assets, kept locally for end-to-end login/game -# testing but not part of the server source tree. +# testing but not part of the server source tree. Binary/3DData is the +# separate, already-pruned subset of this data the server itself actually +# reads (STB definitions, quest scripts, AIP scripts) and stays tracked. /Client/ /3Ddata/ /3Ddata.zip /KTRose_pre-evo.zip +# Visual Studio / MSVC local IDE state -- machine-specific, never useful to +# another checkout. +.vs/ +*.vcxproj.user +*.suo +*.ncb +*.sdf +*.VC.db + +# Editor/OS cruft and stray backup files left by past edits. +*.bak +*~ +[Cc]opy of * +Thumbs.db +.DS_Store + # Claude Code project-local config /.claude/ diff --git a/Binary/3DData/AI/Copy of EVENT_TREE.AIP b/Binary/3DData/AI/Copy of EVENT_TREE.AIP deleted file mode 100644 index c081fd6..0000000 Binary files a/Binary/3DData/AI/Copy of EVENT_TREE.AIP and /dev/null differ diff --git a/Binary/3DData/CONTROL/RES/Thumbs.db b/Binary/3DData/CONTROL/RES/Thumbs.db deleted file mode 100644 index 45b2c58..0000000 Binary files a/Binary/3DData/CONTROL/RES/Thumbs.db and /dev/null differ diff --git a/Binary/3DData/QUESTDATA/Copy of QC001.QSD b/Binary/3DData/QUESTDATA/Copy of QC001.QSD deleted file mode 100644 index 5acd145..0000000 Binary files a/Binary/3DData/QUESTDATA/Copy of QC001.QSD and /dev/null differ diff --git a/Binary/3DData/STB/Copy of LIST_NPC_S.STL b/Binary/3DData/STB/Copy of LIST_NPC_S.STL deleted file mode 100644 index 33a8bbe..0000000 Binary files a/Binary/3DData/STB/Copy of LIST_NPC_S.STL and /dev/null differ diff --git a/Binary/3DData/STB/LIST_FACEITEM_S_old.STL b/Binary/3DData/STB/LIST_FACEITEM_S_old.STL deleted file mode 100644 index d216b21..0000000 Binary files a/Binary/3DData/STB/LIST_FACEITEM_S_old.STL and /dev/null differ diff --git a/Binary/3DData/STB/LIST_FACEITEM_old.STB b/Binary/3DData/STB/LIST_FACEITEM_old.STB deleted file mode 100644 index 840ff70..0000000 Binary files a/Binary/3DData/STB/LIST_FACEITEM_old.STB and /dev/null differ diff --git a/Binary/3DData/STB/LIST_QUEST_S.bak b/Binary/3DData/STB/LIST_QUEST_S.bak deleted file mode 100644 index cf5a2ac..0000000 Binary files a/Binary/3DData/STB/LIST_QUEST_S.bak and /dev/null differ diff --git a/Binary/CharServer.exe b/Binary/CharServer.exe deleted file mode 100644 index b32d749..0000000 Binary files a/Binary/CharServer.exe and /dev/null differ diff --git a/Binary/LoginServer.exe b/Binary/LoginServer.exe deleted file mode 100644 index 08929af..0000000 Binary files a/Binary/LoginServer.exe and /dev/null differ diff --git a/Binary/WorldServer.exe b/Binary/WorldServer.exe deleted file mode 100644 index 438cea4..0000000 Binary files a/Binary/WorldServer.exe and /dev/null differ diff --git a/Binary/libmysql.dll b/Binary/libmysql.dll deleted file mode 100644 index 21439d9..0000000 Binary files a/Binary/libmysql.dll and /dev/null differ diff --git a/Binary/pthreadGC.dll b/Binary/pthreadGC.dll deleted file mode 100644 index e168c97..0000000 Binary files a/Binary/pthreadGC.dll and /dev/null differ diff --git a/Binary/pthreadGC2.dll b/Binary/pthreadGC2.dll deleted file mode 100644 index 5579a8c..0000000 Binary files a/Binary/pthreadGC2.dll and /dev/null differ diff --git a/Binary/pthreadVC2.dll b/Binary/pthreadVC2.dll deleted file mode 100644 index fcb5d9d..0000000 Binary files a/Binary/pthreadVC2.dll and /dev/null differ diff --git a/CharServer/CharServer.vcxproj.user b/CharServer/CharServer.vcxproj.user deleted file mode 100644 index 3dd7161..0000000 --- a/CharServer/CharServer.vcxproj.user +++ /dev/null @@ -1,7 +0,0 @@ - - - - ..\Binary - WindowsLocalDebugger - - \ No newline at end of file diff --git a/Login/Login.vcxproj.user b/Login/Login.vcxproj.user deleted file mode 100644 index 3dd7161..0000000 --- a/Login/Login.vcxproj.user +++ /dev/null @@ -1,7 +0,0 @@ - - - - ..\Binary - WindowsLocalDebugger - - \ No newline at end of file diff --git a/Servers/.vs/Servers/v16/.suo b/Servers/.vs/Servers/v16/.suo deleted file mode 100644 index f9e4740..0000000 Binary files a/Servers/.vs/Servers/v16/.suo and /dev/null differ diff --git a/Servers/.vs/Servers/v16/Browse.VC.db b/Servers/.vs/Servers/v16/Browse.VC.db deleted file mode 100644 index 2d5db39..0000000 Binary files a/Servers/.vs/Servers/v16/Browse.VC.db and /dev/null differ diff --git a/Servers/.vs/Servers/v16/Solution.VC.db b/Servers/.vs/Servers/v16/Solution.VC.db deleted file mode 100644 index 676c136..0000000 Binary files a/Servers/.vs/Servers/v16/Solution.VC.db and /dev/null differ diff --git a/Servers/Servers.vcxproj.user b/Servers/Servers.vcxproj.user deleted file mode 100644 index 88a5509..0000000 --- a/Servers/Servers.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Src/World Server/Copy of battle.cpp b/Src/World Server/Copy of battle.cpp deleted file mode 100644 index 1edf3bd..0000000 --- a/Src/World Server/Copy of battle.cpp +++ /dev/null @@ -1,847 +0,0 @@ -/* - Rose Online Server Emulator - Copyright (C) 2006,2007 OSRose Team http://www.osrose.net - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - depeloped with Main erose/hrose source server + some change from the original eich source -*/ -#include "character.h" -#include "worldserver.h" - -void CCharacter::DoAttack( ) -{ - //if(Status->Sleep <= 0xff) - //{ - // ClearBattle( Battle ); - // return; // can't take any action while we are asleep can we? - //} - //Log(MSG_INFO,"skill type %i selected. Chartype = %i",Battle->atktype, CharType); - if(Battle->iscasting == 1) - { - CCharacter* Enemy = GetCharTarget( ); - if(Enemy == NULL) - { - ClearBattle( Battle ); - return; - } - //Log(MSG_DEBUG,"Iscasting detected as true. Reset to false."); - if(CanAttack()) - { - if(IsPlayer()) - { - Log(MSG_DEBUG,"Should reach here once on normal attack. iscasting state = %i",Battle->iscasting); - } - ClearBattle( Battle ); - - StartAction(Enemy, NORMAL_ATTACK, 0); - - return; - } - else - { - return; - } - } - if(!CanAttack()) - { - return; - } - if(IsSummon()) - { - CCharacter* Enemy = GetCharTarget( ); - if(Enemy == NULL || (Battle->atktype != SKILL_AOE && Battle->atktype != BUFF_AOE)) - { - //Log(MSG_DEBUG,"No Enemy found"); - ClearBattle( Battle ); - return; - } - if(this == Enemy) //summoned monster is attacking itself. It has been observed to happen - { - //Log(MSG_INFO,"Clearing Battle for this summon"); - ClearBattle( Battle ); - return; - } - if(Enemy->IsSummon()) - { - CMonster* thisMonster = reinterpret_cast(this); - if(thisMonster == NULL) - { - ClearBattle( Battle ); - return; - } - CMonster* otherMonster = reinterpret_cast(Enemy); - if(otherMonster == NULL) - { - ClearBattle( Battle ); - return; - } - if(thisMonster->owner == otherMonster->owner) - { - //Log(MSG_INFO,"Clearing Battle for this summon"); - ClearBattle( Battle ); - return; - } - } - } - CMap* map = GServer->MapList.Index[Position->Map]; - //Log(MSG_INFO,"DoAttack Battle Attack type = %i",Battle->atktype); - switch(Battle->atktype) - { - case NORMAL_ATTACK://normal attack - { - //if(!Status->CanAttack) - // return; //can't attack right now. - CCharacter* Enemy = GetCharTarget( ); - if(Enemy == NULL) - { - ClearBattle( Battle ); - return; - } - if(Enemy == this) - { - //Log(MSG_INFO,"WTF?? I AM trying to attack myself"); - ClearBattle( Battle ); - } - if(IsTargetReached( Enemy )) - { - //if(IsMonster()) - // Log(MSG_INFO,"Monster is trying to hit the player"); - NormalAttack( Enemy ); - if (Enemy->IsMonster()) // do monster AI script when monster is attacked. - { - CMonster* monster = GServer->GetMonsterByID(Enemy->clientid, Enemy->Position->Map); - if(monster == NULL)return; - //monster->DoAi(monster->thisnpc->AI, 3); - monster->DoAi(monster->monAI, 3); - } - } - } - break; - case SKILL_ATTACK://skill attack - { - CCharacter* Enemy = GetCharTarget( ); - if(Enemy == NULL) - { - ClearBattle( Battle ); - return; - } - CSkills* skill = GServer->GetSkillByID( Battle->skillid ); - if(skill == NULL) - { - //ClearBattle( Battle ); - return; - } - if(IsTargetReached( Enemy, skill )) - { - SkillAttack( Enemy, skill ); - if (Enemy->IsMonster()) - { - CMonster* monster = GServer->GetMonsterByID(Enemy->clientid, Enemy->Position->Map); - if(monster == NULL)return; - monster->DoAi(monster->monAI, 3); - } - } - } - break; - case SKILL_BUFF://buffs - { - CCharacter* Enemy = GetCharTarget( ); - if(Enemy == NULL) - { - //Log(MSG_DEBUG,"this target is NULL"); - ClearBattle( Battle ); - return; - } - CSkills* skill = GServer->GetSkillByID( Battle->skillid ); - if(skill == NULL) - { - //Log(MSG_DEBUG,"this skill is NULL"); - return; - } - if(IsTargetReached( Enemy, skill )) - { - //Log(MSG_DEBUG,"Skill successfully cast"); - BuffSkill( Enemy, skill ); - } - } - break; - case SKILL_AOE: - //case SKILL_SELF: //this is impossible. it can never be set - case AOE_TARGET: - { - //Log(MSG_DEBUG,"Called skill type %i",Battle->atktype); - CCharacter* Enemy = NULL; - CSkills* skill = GServer->GetSkillByID( Battle->skillid ); - if(skill == NULL) - { - ClearBattle( Battle ); - return; - } - if(Battle->atktype == AOE_TARGET) - { - float distance = GServer->distance( Position->current, Position->destiny ); - if(distance <= skill->range) - { - Position->destiny = Position->current; - AoeSkill( skill, Enemy ); - } - } - else - { - Position->skilltargetpos = Position->current; - AoeSkill( skill, NULL ); - } - } - break; - case BUFF_SELF: - { - // return; // can't cast skills right now - CSkills* skill = GServer->GetSkillByID( Battle->skillid ); - if(skill == NULL) - { - //ClearBattle( Battle ); - return; - } - BuffSkill( this, skill ); - } - break; - case BUFF_AOE: - { - //Log(MSG_INFO,"BUFF AOE selected"); - CSkills* skill = GServer->GetSkillByID( Battle->skillid ); - if(skill == NULL) - { - //ClearBattle( Battle ); - - return; - } - AoeBuff( skill ); - } - break; - default: - return; - break; - } -} - - -// do normal attack -void CCharacter::NormalAttack( CCharacter* Enemy ) -{ - Enemy->OnBeAttacked( this ); - Position->destiny = Position->current; - // PY code - float mod = 0; - if(IsPlayer()) - { - mod = 23 + (Stats->Level / 1.5); - } - else - { - mod = 23 + (Stats->Level / 4); - - } - float attack = 0; - if(Stats->magicattack == 1) - { - attack = (float) Stats->Attack_Power / Enemy->Stats->Magic_Defense; - attack *= mod; - } - else - { - attack = (float) Stats->Attack_Power / Enemy->Stats->Defense; - attack *= mod; - } - //PY end - if(attack < 5) attack = 5; - float d_attack = attack / 100; - mod = GServer->RandNumber( 0, 10 ) * d_attack; - attack += mod; - long int hitpower = (long int)floor(attack + GServer->RandNumber(0, 10)); - if(IsPlayer( )) //temp fix to find balance btw monster and player - { - hitpower = (long int)floor(attack * (GServer->Config.PlayerDmg/100.00)); - hitpower+=((hitpower*(Stats->ExtraDamage))/100); - } - if(IsMonster( )) //temp fix to find balance btw monster and player - hitpower = (long int)floor(attack * (GServer->Config.MonsterDmg/100.00)); - bool critical = false; - if(hitpower <= 5) - { - hitpower = 5; - } - else - { - if(GServer->RandNumber(0,300)Critical) - { - hitpower = (long int)floor(hitpower * 1.5); - critical = true; - } - } - // dodge - unsigned int hitvalue = (unsigned int)floor((double)(Stats->Accury * 100 / Enemy->Stats->Dodge)); - if(hitvalue>100) hitvalue = 100; - if(GServer->RandNumber( 0, 100 )>hitvalue) - hitpower = 0; // dodged - if (hitpower > 0x7ff)//2047 packet size limit. - { - hitpower=0x7ff; - } - - //maybe this little line here will fix my ghosty problem - //they are definitely attacking. But no animation so maybe atktarget is empty - Battle->atktarget = Battle->target; - //Well it does make the damage show up at teh client but the animation is still dodgey - - if(IsMonster()) - { - //Log(MSG_INFO,"Monster hits player for %i damage. Attack target = %i",hitpower,Battle->atktarget); - } - //Log( MSG_INFO, "hitpower %i. Attack %f ", hitpower,attack ); - if(!Enemy->IsSummon( ) && Enemy->IsMonster( )) - { - Enemy->AddDamage( this, hitpower ); - Enemy->damagecounter += hitpower;// is for AI - } - Enemy->Stats->HP -= hitpower; - if(IsPlayer()) - Log(MSG_DEBUG,"Player attack did damage %i",hitpower); - if(IsMonster()) - Log(MSG_DEBUG,"Monster attack did damage %i",hitpower); - - - - BEGINPACKET( pak, 0x799 ); - ADDWORD ( pak, clientid ); - ADDWORD ( pak, Battle->atktarget ); - - if(Enemy->IsDead()) - { - CDrop* thisdrop = NULL; - ADDWORD ( pak, (hitpower | ( critical?0xb000:0x8000 ) )); - if(!Enemy->IsSummon( ) && !Enemy->IsPlayer( )) - { - thisdrop = Enemy->GetDrop( ); - if(thisdrop != NULL) - { - ADDFLOAT ( pak, thisdrop->pos.x*100 ); - ADDFLOAT ( pak, thisdrop->pos.y*100 ); - if(thisdrop->type == 1) - { - ADDWORD( pak, 0xccdf ); - ADDDWORD( pak, thisdrop->amount ); - } - else - { - ADDWORD ( pak, GServer->BuildItemHead( thisdrop->item ) ); - ADDDWORD ( pak, GServer->BuildItemData( thisdrop->item ) ); - } - ADDWORD ( pak, thisdrop->clientid ); - ADDWORD ( pak, thisdrop->owner ); - CMap* map = GServer->MapList.Index[thisdrop->posMap]; - map->AddDrop( thisdrop ); - } - } - GServer->SendToVisible( &pak, Enemy, thisdrop ); - OnEnemyDie( Enemy ); - } - else - { - ADDWORD ( pak, (hitpower|(hitpower>0?(critical?0x4000:0):0))); - GServer->SendToVisible( &pak, Enemy ); - } - ReduceABC( ); - Battle->lastAtkTime = clock( ); -} - -// do skill attack -bool CCharacter::SkillAttack( CCharacter* Enemy, CSkills* skill ) -{ - Position->destiny = Position->current; - //if(Battle->castTime == 0) - //{ - BEGINPACKET( pak, 0x7bb ); - ADDWORD ( pak, clientid ); - GServer->SendToVisible( &pak, this ); - // Battle->castTime = clock(); - // return true; - //} - //else - //{ - // clock_t etime = clock() - Battle->castTime; - // if(etime < SKILL_DELAY) - // return true; - //} - //Battle->castTime = 0; - UseAtkSkill( Enemy, skill ); - Stats->MP -= (skill->mp - (skill->mp * Stats->MPReduction / 100)); - if(Stats->MP < 0) - Stats->MP = 0; - //Battle->atktype = NORMAL_ATTACK; - //Battle->skilltarget = 0; - //Battle->atktarget = Battle->target; - //Battle->skillid = 0; - GServer->DoSkillScript( this, skill ); - Battle->lastAtkTime = clock( ); - if(Enemy->IsDead()) - ClearBattle(Battle); - Battle->iscasting = 1; - //Log(MSG_DEBUG,"Cast a skill. Iscasting set to true"); - return true; -} - -// do buff skill -bool CCharacter::BuffSkill( CCharacter* Target, CSkills* skill ) -{ - Position->destiny = Position->current; - //if(Battle->castTime == 0) - //{ - BEGINPACKET( pak, 0x7bb ); - ADDWORD ( pak, clientid ); - GServer->SendToVisible( &pak, (CCharacter*)this ); - // Battle->castTime = clock(); - // return true; - //} - //else - //{ - // clock_t etime = clock() - Battle->castTime; - // if(etime < SKILL_DELAY) - // return true; - //} - //Battle->castTime = 0; - //Log(MSG_DEBUG,"applied buff skill %i",skill->id); - UseBuffSkill( Target, skill ); - Stats->MP -= (skill->mp - (skill->mp * Stats->MPReduction / 100)); - if(Stats->MP < 0) Stats->MP = 0; - GServer->DoSkillScript( this, skill ); //summons a monster. Why do we do this for all skills? - if(!IsMonster()) - { - ClearBattle( Battle ); // clear battle for players when they use buff skills - //Battle->bufftarget = 0; - //Battle->skilltarget = 0; - //Battle->skillid = 0; - //Battle->atktype = NORMAL_ATTACK; - } - else //Monsters need to be reset to normal attack and clear skill attacks. - { - //Battle->atktarget = Battle->target; - //Battle->bufftarget = 0; - //Battle->skilltarget = 0; - //Battle->skillid = 0; - //Battle->atktype = NORMAL_ATTACK; - //StartAction(Target, NORMAL_ATTACK); - } - Battle->lastAtkTime = clock( ); - Battle->iscasting = 1; - return true; -} -//arnold -// do AoE skill -bool CCharacter::AoeSkill( CSkills* skill, CCharacter* Enemy ) -{ - Position->destiny = Position->current; - //Log(MSG_INFO,"Doing AOE Skill"); - //if(Battle->castTime == 0) - //{ - BEGINPACKET( pak, 0x7bb ); - ADDWORD ( pak, clientid ); - GServer->SendToVisible( &pak, (CCharacter*)this ); - // Battle->castTime = clock(); - // return true; - //} - //else - //{ - // clock_t etime = clock() - Battle->castTime; - // if(etime < SKILL_DELAY) - // return true; - //} - //Battle->castTime = 0; - CMap* map = GServer->MapList.Index[Position->Map]; - - //PY replacement code - if(IsPlayer() || IsSummon()) - { - for(UINT i=0;iMonsterList.size();i++) - { - CMonster* monster = map->MonsterList.at(i); - if(monster == NULL) continue; - if(monster->clientid == clientid) continue; - if(monster->IsSummon( ) && (map->allowpvp == 0 || monster->owner == clientid)) continue; - if(GServer->IsMonInCircle( Position->skilltargetpos, monster->Position->current,(float)skill->aoeradius + 1)) - UseAtkSkill( (CCharacter*) monster, skill ); - } - } - if(IsMonster() && !IsSummon()) - { - for(UINT i=0;iPlayerList.size();i++) - { - CPlayer* player = map->PlayerList.at(i); - if(player == NULL)continue; - if(player->clientid == clientid) continue; - if(GServer->IsMonInCircle( Position->skilltargetpos,player->Position->current,(float)skill->aoeradius+1)) - UseAtkSkill( (CCharacter*) player, skill ); - } - } - //PY end - - // this code appears to me to be completely wrong replaced with code above - /* - for(UINT i=0;iMonsterList.size();i++) - { - CMonster* monster = map->MonsterList.at(i); - if(monster->clientid == clientid) continue; - if(IsSummon( ) || IsPlayer( )) - { - if(monster->IsSummon( ) && (map->allowpvp==0 || monster->owner == clientid)) continue; - } - else - { - if(!monster->IsSummon( )) continue; - } - if(GServer->IsMonInCircle( Position->skilltargetpos, monster->Position->current,(float)skill->aoeradius + 1)) - UseAtkSkill( (CCharacter*) monster, skill ); - } - if(map->allowpvp!=0 || (IsMonster( ) && !IsSummon( ))) - { - for(UINT i=0;iPlayerList.size();i++) - { - CPlayer* player = map->PlayerList.at(i); - if(player->clientid==clientid) continue; - if(GServer->IsMonInCircle( Position->skilltargetpos,player->Position->current,(float)skill->aoeradius+1)) - UseAtkSkill( (CCharacter*) player, skill ); - } - }*/ - Battle->iscasting = 1; - //Log(MSG_DEBUG,"Cast a skill. Iscasting set to true"); - if(Enemy != NULL) - { - if(Enemy->IsDead( )) - ClearBattle( Battle ); - } - else - ClearBattle( Battle ); - Stats->MP -= (skill->mp - (skill->mp * Stats->MPReduction / 100)); - if(Stats->MP < 0) Stats->MP = 0; - Battle->lastAtkTime = clock( ); - - return true; -} - -bool CCharacter::AoeBuff( CSkills* skill ) -{ - //Log(MSG_INFO,"BUFF AOE called"); - Position->destiny = Position->current; - BEGINPACKET( pak, 0x7bb ); - ADDWORD ( pak, clientid ); - GServer->SendToVisible( &pak, (CCharacter*)this ); - CMap* map = GServer->MapList.Index[Position->Map]; - - if(CharType != 2) //player || Summon || NPC. Anything that is not a monster - { - for(UINT i=0;iPlayerList.size();i++) - { - CPlayer* player = map->PlayerList.at(i); - if(player == NULL)continue; - switch(skill->target) - { - case 1: //tPartyMember - if(player->Party->party == GetParty()) - { - //Log(MSG_INFO,"Applying AOE buff as long as I can find a close enough party member"); - if (player == this) //it is me so I had better cast it anyway ^-^ - { - UseBuffSkill( (CCharacter*)player, skill ); - } - else if(player->Party->party != NULL) // Don't cast the skill on players who are not in any party at all. - { - if(GServer->IsMonInCircle( Position->current,player->Position->current,(float)skill->aoeradius + 1)) - UseBuffSkill( (CCharacter*)player, skill ); - } - } - break; - case 2: //tClanMember - if (player->Clan == GetClan( ) && (player->Clan != 0 || player == this)) - { - //Log(MSG_INFO,"Applying AOE buff as long as I can find a close enough clan member"); - if(GServer->IsMonInCircle( Position->current, player->Position->current, (float)skill->aoeradius + 1 ) ) - UseBuffSkill( (CCharacter*)player, skill ); - } - break; - case 3: //tAlly - case 7: //tAllCharacters - case 8: //tAllMembers. all characters - { - Log(MSG_INFO,"Applying AOE buff as long as I can find a close enough allied Player"); - if(GServer->IsMonInCircle( Position->current,player->Position->current,(float)skill->aoeradius + 1)) - UseBuffSkill( (CCharacter*)player, skill ); - } - break; - case 5: //tHostileCharacter - { - if (CharType == 2) - { - //Log(MSG_INFO,"Applying AOE buff as long as I can find a close enough hostile Player"); - if(GServer->IsMonInCircle( Position->current,player->Position->current,(float)skill->aoeradius + 1)) - UseBuffSkill( (CCharacter*)player, skill ); - } - } - break; - } - } - } - else if (CharType == 2) //monster - { - for(UINT i=0;iMonsterList.size();i++) - { - CMonster* monster = map->MonsterList.at(i); - if(monster == NULL)continue; - switch(skill->target) - { - case tPartyMember: // party - break; - case 2: //tClanMember - break; - case 3: //tAlly - case 7: //tAllCharacters - case 8: //tAllMembers. all characters - { - //Log(MSG_INFO,"Applying AOE buff as long as I can find a close enough monster"); - if(GServer->IsMonInCircle( Position->current,monster->Position->current,(float)skill->aoeradius + 1)) - UseBuffSkill( (CCharacter*)monster, skill ); - } - break; - case tHostileCharacter: - break; - } - } - } - Stats->MP -= (skill->mp - (skill->mp * Stats->MPReduction / 100)); - if(Stats->MP < 0) Stats->MP = 0; - //Battle->atktarget = Battle->target; - //Battle->bufftarget = 0; - //Battle->skilltarget = 0; - //Battle->skillid = 0; - //Battle->atktype = NORMAL_ATTACK; - ClearBattle( Battle ); - Battle->lastAtkTime = clock( ); - Battle->iscasting = 1; - return true; -} - - - -// use skill attack -void CCharacter::UseAtkSkill( CCharacter* Enemy, CSkills* skill, bool deBuff) -{ - long int skillpower = skill->atkpower; - UINT weapontype = 0; - float mod = 0; - float attack = 0; - if(IsPlayer()) - { - mod = 20 + (Stats->Level / 2); - } - else - { - mod = 15 + (Stats->Level / 2); - } - if(skill->skilltype == 6 || skill->skilltype == 7) //magical damage - { - attack = skillpower / (Enemy->Stats->Magic_Defense / 2); - } - else - { - attack = skillpower / (Enemy->Stats->Defense / 2); - } - attack *= mod; - attack += (Stats->Attack_Power / 2); // let's add our AP to the skillpower to make it worthwhile to cast skills. - - skillpower = (int)attack; - bool bflag = false; - Enemy->OnBeAttacked( this ); - if(skillpower <= 0) skillpower = 0; - if(IsPlayer()) - { - skillpower += (int)(skillpower * (Stats->ExtraDamage))/100; - } - if (skill->atkpower == 0) - { - skillpower = 0; // If the skill has a 0 atk power, it isn't meant to damage - Log( MSG_INFO, "This skill does no damage" ); - //ClearBattle( Battle ); - return; // probably need to add some alternative code here for legitimate skills that have no attack power. - } - if(skillpower >2046)skillpower = 2046; - //Log(MSG_DEBUG,"Cast a skill. damage is %i",skillpower); - if(!Enemy->IsSummon( ) && Enemy->IsMonster( )) - { - Enemy->AddDamage( this, skillpower ); - Enemy->damagecounter += skillpower;// is for AI - } - Enemy->Stats->HP -= skillpower; - if(IsPlayer()) - Log(MSG_DEBUG,"Player Spell did damage %i",skillpower); - if(IsMonster()) - Log(MSG_DEBUG,"Monster spell did damage %i",skillpower); - BEGINPACKET( pak, 0x7b6 ); - ADDWORD ( pak, Enemy->clientid ); - ADDWORD ( pak, clientid ); - ADDDWORD ( pak, 0x000007f8 ); - ADDBYTE ( pak, 0x00 ); - if (Enemy->Stats->HP<1) - { - ADDWORD ( pak, skillpower + 0x8000 ); - } - else - { - ADDWORD ( pak, skillpower + 0x2000 ); - } - if(Enemy->IsDead()) - { - //Log(MSG_DEBUG,"Enemy died"); - CDrop* thisdrop = NULL; - ADDDWORD ( pak, 16 ); - if(!Enemy->IsSummon( ) && !Enemy->IsPlayer( )) - { - thisdrop = Enemy->GetDrop( ); - if(thisdrop != NULL) - { - ADDFLOAT ( pak, thisdrop->pos.x*100 ); - ADDFLOAT ( pak, thisdrop->pos.y*100 ); - if(thisdrop->type==1) - { - ADDWORD( pak, 0xccdf ); - ADDDWORD( pak, thisdrop->amount ); - } - else - { - ADDWORD ( pak, GServer->BuildItemHead( thisdrop->item ) ); - ADDDWORD ( pak, GServer->BuildItemData( thisdrop->item ) ); - } - ADDWORD ( pak, thisdrop->clientid ); - ADDWORD ( pak, thisdrop->owner ); - CMap* map = GServer->MapList.Index[thisdrop->posMap]; - map->AddDrop( thisdrop ); - } - } - GServer->SendToVisible( &pak, Enemy, thisdrop ); - OnEnemyDie( Enemy ); - } - else - { - ADDDWORD ( pak, 4 ); - GServer->SendToVisible( &pak, Enemy ); - bflag = GServer->AddBuffs( skill, Enemy, GetInt( ) ); - - //Send (de)buff information to the whole world - if(skill->nbuffs > 0 && bflag) - { - BEGINPACKET( pak, 0x7b5 ); - ADDWORD ( pak, Battle->skilltarget ); - ADDWORD ( pak, clientid ); - ADDWORD ( pak, Battle->skillid ); - ADDWORD ( pak, GetInt( ) ); - ADDBYTE ( pak, skill->nbuffs ); - GServer->SendToVisible( &pak, Enemy ); - } - } - if (deBuff) return; - //Send skill animation to the world - RESETPACKET( pak, 0x7b9); - ADDWORD ( pak, clientid); - ADDWORD ( pak, Battle->skillid); - ADDWORD ( pak, 1); - GServer->SendToVisible( &pak, this ); - Battle->bufftarget = 0; - Battle->skilltarget = 0; - Battle->skillid = 0; - //Battle->atktype = NORMAL_ATTACK; -} - -// use buff skill -void CCharacter::UseBuffSkill( CCharacter* Target, CSkills* skill ) -{ - bool bflag = false; - bflag = GServer->AddBuffs( skill, Target, GetInt( ) ); - if(skill->nbuffs > 0 && bflag == true) - { - BEGINPACKET( pak, 0x7b5 ); - ADDWORD ( pak, Target->clientid ); - ADDWORD ( pak, clientid ); - ADDWORD ( pak, Battle->skillid ); - ADDWORD ( pak, GetInt( )/4 ); - ADDBYTE ( pak, skill->nbuffs ); - GServer->SendToVisible( &pak, Target ); - //Log(MSG_DEBUG,"Buff Skill. buffs applied 1"); - } - - BEGINPACKET( pak, 0x7b9); - ADDWORD ( pak, clientid); - ADDWORD ( pak, Battle->skillid); - ADDWORD ( pak, 1); - GServer->SendToVisible( &pak, this ); - //Log(MSG_DEBUG,"Buff Skill. buffs applied 2 nbuffs = %i",skill->nbuffs); - //Log(MSG_INFO,"Target HP = %i",Target->Stats->HP); -} - -// Use a skill -bool CCharacter::UseSkill( CSkills* skill, CCharacter *Target ) -{ - if (skill->atkpower > 0) - { - Log(MSG_INFO, "Need to do %i%s %s in range %i to target %i", - ( skill->atkpower ), - ( (skill->range > 0) ? " AOE" : "" ), - ( (GServer->isSkillTargetFriendly(skill)) ? "healing" : "damage" ), - ( skill->range ), - ( skill->target ) ); - } - for (int i = 0; i < 2; i++) { - Log(MSG_INFO, "Status ID: %i", skill->status[i]); - if (skill->status[i] == 0) continue; - CStatus* status = GServer->GetStatusByID(skill->status[i]); - if (status == NULL) continue; - /************************ - We'll probably need to use status->decrease (Figure out whether buf is up/down - status->repeat will tell us whether it's a one-time (Stat Boost [2]), repeat - (Recovery, continueing damage [1]) or Special (Status Effect [3]). - ************************/ - if (status->repeat == 1) // Continuous - { - Log(MSG_INFO, "Need to take stat %i and %s it by %i%s over %i seconds", skill->buff[i], - ((status->decrease) ? "decrease" : "increase"), - ((skill->value1[i] != 0) ? skill->value1[i] : skill->value2[i]), - ((skill->value1[i] != 0) ? "" : "%"), skill->duration); - } - else if (status->repeat == 2) // Once (Stat Boost) - { - Log(MSG_INFO, "Need to take stat %i and %s it by %i%s for %i seconds", skill->buff[i], - ((status->decrease) ? "decrease" : "increase"), - ((skill->value1[i] != 0) ? skill->value1[i] : skill->value2[i]), - ((skill->value1[i] != 0) ? "" : "%"), skill->duration); - - } else if (status->repeat == 3) // Status Effect (Poison,etc) - { - Log(MSG_INFO, "Need to give user status effect %i for %i seconds", skill->buff[i], - ((skill->value1[i] != 0) ? skill->value1[i] : skill->value2[i]), - ( skill->duration ) ); - - } - } - return true; -} - - diff --git a/Src/World Server/Copy of charfunctions.cpp b/Src/World Server/Copy of charfunctions.cpp deleted file mode 100644 index 69f0bab..0000000 --- a/Src/World Server/Copy of charfunctions.cpp +++ /dev/null @@ -1,570 +0,0 @@ -/* - Rose Online Server Emulator - Copyright (C) 2006,2007 OSRose Team http://www.osrose.net - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - developed with Main erose/hrose source server + some change from the original eich source -*/ -#include "character.h" -#include "worldserver.h" - -// return true if this character is monster -bool CCharacter::IsMonster( ) -{ - if(CharType == 2 || CharType == 3) - return true; - return false; -} - -// return true if this character is player -bool CCharacter::IsPlayer( ) -{ - if(CharType == 1) - return true; - return false; -} - -//return true if this character is an NPC -bool CCharacter::IsNPC( ) -{ - if(CharType == 4) - return true; - return false; -} - -// return true if HP is lower to 1 -bool CCharacter::IsDead( ) -{ - if(Stats->HP <= 0) - return true; - return false; -} - -// return true if this character is summon -bool CCharacter::IsSummon( ) -{ - if(this == NULL) return false; - if(CharType == 3)// this line is erroring. No idea why - return true; - return false; -} - -// Virtual function [return item drop] -CDrop* CCharacter::GetDrop( ) -{ - return NULL; -} - -// start action [attack] -void CCharacter::StartAction( CCharacter* Target, BYTE action, UINT skillid) -{ - - BEGINPACKET( pak, 0 ); - switch(action) - { - case NORMAL_ATTACK: - { - //Log( MSG_INFO, "case NORMAL_ATTACK"); - if(Target == NULL)return; - RESETPACKET( pak, 0x798 ); - ADDWORD ( pak, clientid ); - ADDWORD ( pak, Target->clientid ); - ADDWORD ( pak, Stats->Move_Speed ); - ADDFLOAT ( pak, Target->Position->current.x * 100 ); - ADDFLOAT ( pak, Target->Position->current.y * 100 ); - Battle->target = Target->clientid; - Battle->atktarget = Target->clientid; - Battle->atktype = action; - Battle->skilltarget = 0; - Battle->bufftarget = 0; - Battle->skillid = 0; - Position->destiny = Target->Position->current; - Position->lastMoveTime = clock(); - } - break; - case SKILL_ATTACK: //Log( MSG_INFO, "case SKILL_ATTACK"); - case SKILL_BUFF: - { - if(Target == NULL)return; - RESETPACKET( pak, 0x7b3 ); - ADDWORD ( pak, clientid ); - ADDWORD ( pak, Target->clientid ); - ADDWORD ( pak, skillid ); - ADDWORD ( pak, 0x0000 ); - ADDFLOAT ( pak, Target->Position->current.x * 100 ); - ADDFLOAT ( pak, Target->Position->current.y * 100 ); - Battle->target = Target->clientid; - - if(action == SKILL_ATTACK) - { - //Log( MSG_INFO, "case SKILL_ATTACK"); - Battle->skilltarget = Target->clientid; - Battle->bufftarget = 0; - } - else - { - //Log( MSG_INFO, "case SKILL_BUFF"); - Battle->bufftarget = Target->clientid; - Battle->skilltarget = 0; - } - - Battle->atktype = action; - Position->destiny = Target->Position->current; - Battle->skillid = skillid; - Position->lastMoveTime = clock(); - } - break; - case SKILL_AOE://Log( MSG_INFO, "case SKILL_AOE"); - case BUFF_SELF://Log( MSG_INFO, "case BUFF_SELF"); - case BUFF_AOE: - { - //Log( MSG_INFO, "case BUFF_AOE"); - RESETPACKET( pak, 0x7b2); - ADDWORD ( pak, clientid ); - ADDWORD ( pak, skillid ); - Battle->atktype = action; - Battle->skillid = skillid; - //Log( MSG_INFO, "BUFF_AOE packet sent"); - } - break; - case AOE_TARGET: - { - //Log( MSG_INFO, "case AOE_TARGET"); - //Target is NULL for this function when cast by a player - //Target is NOT NULL when it comes from a monster - if(Target != NULL) //monster attack - { - Position->skilltargetpos.x = Target->Position->current.x; - Position->skilltargetpos.y = Target->Position->current.y; - } - RESETPACKET( pak, 0x7b4 ); - ADDWORD ( pak, clientid ); - ADDWORD ( pak, skillid ); - ADDFLOAT ( pak, Position->skilltargetpos.x * 100 ); - ADDFLOAT ( pak, Position->skilltargetpos.y * 100 ); - Battle->atktype = action; - Battle->skillid = skillid; - Battle->skilltarget = 0; - Battle->bufftarget = 0; - } - break; - default: - return; - break; - } - GServer->SendToVisible( &pak, this ); - Battle->contatk = true; - - //Log(MSG_INFO,"Battle Attacktype = %i",Battle->atktype); - return; -} - -bool CCharacter::IsOnBattle( ) -{ - if(Battle->atktype == 0) - { - if(Battle->iscasting == 1) - { - clock_t etime = clock() - Battle->lastAtkTime; - if( etime < CLOCKS_PER_SEC * 100 / Stats->Attack_Speed ) - { - //Log(MSG_DEBUG,"Iscasting is true while NOT in battle. Reset to false."); - Battle->iscasting = 0; - return false; - } - } - return false; - } - switch(Battle->atktype) - { - case NORMAL_ATTACK: - { - if(Battle->atktarget != 0) return true; - } - break; - case SKILL_ATTACK: - case AOE_TARGET: - { - if(Battle->skilltarget != 0 && Battle->skillid != 0) return true; - } - break; - case SKILL_BUFF: - { - if(Battle->bufftarget != 0 && Battle->skillid != 0) return true; - } - break; - case SKILL_AOE: - //case SKILL_SELF: //no such skill type - case BUFF_SELF: - case BUFF_AOE: - { - if(Battle->skillid != 0) return true; - } - break; - default: return false; - } -} - -bool CCharacter::CanAttack( ) -{ - - clock_t etime = clock() - Battle->lastAtkTime; - if (Stats->Attack_Speed < 1) - { - Log( MSG_INFO, "weapon with no attackspeed."); - return false; - } - if(Battle->iscasting == 1) - { - if( etime < CLOCKS_PER_SEC * 25 / Stats->Attack_Speed ) //should make the delay 4 times longer - { - //if(IsPlayer()) - // Log(MSG_INFO,"Cannot use magic attack yet. Last attack time = %i",Battle->lastAtkTime); - return false; - } - else - { - Battle->iscasting = 0; - //if(IsPlayer()) - // Log(MSG_INFO,"OK Now we can use a new (magic or normal) attack."); - return true; - } - } - else //normal attack - { - if( etime < CLOCKS_PER_SEC * 100 / Stats->Attack_Speed ) - { - //if(IsPlayer()) - // Log(MSG_INFO,"Cannot attack yet. Last attack time = %i",Battle->lastAtkTime); - return false; - } - //if(IsPlayer()) - // Log(MSG_INFO,"OK Now we can use a normal attack"); - } - return true; -} - -// return true if target is reached -bool CCharacter::IsTargetReached( CCharacter* Enemy, CSkills* skill ) -{ - CMap* map = GServer->MapList.Index[Position->Map]; - if(map == NULL)return false; - float distance = GServer->distance( Position->current, Enemy->Position->current ); - if(skill == NULL) //it's a normal attack - { - if(distance <= Stats->Attack_Distance) - { - return true; - } - else - { - Position->destiny = Enemy->Position->current; - } - } - else - { - if(distance <= skill->range) - { - return true; - } - else - { - Position->destiny = Enemy->Position->current; - } - } - //Log(MSG_INFO,"Monster cannot attack. Too far away"); - return false; -} - -// return true if the character is moving -bool CCharacter::IsMoving( ) -{ - if(Position->current.x == Position->destiny.x && Position->current.y == Position->destiny.y ) - return false; - return true; -} - -// VIRTUAL [add player damage] -void CCharacter::AddDamage( CCharacter* enemy, long int hitpower) -{ - -} - -// return character target -CCharacter* CCharacter::GetCharTarget( ) -{ - CCharacter* thistarget = GServer->MapList.Index[Position->Map]->GetCharInMap( Battle->target ); - if (thistarget != NULL) - return thistarget; - //if I don't currently have a target then return the character who just hit me - return GServer->MapList.Index[Position->Map]->GetCharInMap( Battle->hitby ); -} - -// VIRTUAL [reduce ammon/bullets/cannons] -void CCharacter::ReduceABC( ) -{ - -} - -// VIRTUAL [get extra buff value] -int CCharacter::GetEVBuff( ) -{ - return 0; -} - -// VIRTUAL [return intelligence] -unsigned int CCharacter::GetInt( ) -{ - return 15; -} - - -// Check For Debuffs -void CCharacter::RefreshBuff( ) -{ - bool bflag = false; - for( UINT i=0;i<30;i++) - { - if(MagicStatus[i].Buff == 0) continue; - clock_t etime = clock() - MagicStatus[i].BuffTime; - if( etime >= MagicStatus[i].Duration * CLOCKS_PER_SEC ) - { - switch(MagicStatus[i].Status) - { - case 18: // attack power up - case 19: // attack power down - case 48: // attack power up - if(i<15) - Status->Attack_up = 0xff; - else - Status->Attack_down = 0xff; - Stats->Attack_Power = GetAttackPower( ); - break; - case 20: // def up - case 21: // def down - case 49: // def up - if(i<15) - Status->Defense_up= 0xff; - else - Status->Defense_down = 0xff; - Stats->Defense = GetDefense( ); - break; - case 24: //accuracy up - case 25: //accuracy down - case 51: //attack accuracy up. - if(i<15) - Status->Accury_up= 0xff; - else - Status->Accury_down = 0xff; - Stats->Accury = GetAccury( ); - break; - case 22: // macic resistance up - case 23: // magic resistance down - case 50: // magic resistance up - if(i<15) - Status->Magic_Defense_up = 0xff; - else - Status->Magic_Defense_down = 0xff; - Stats->Magic_Defense = GetMagicDefense( ); - break; - case 28: //dodge up - case 29: //dodge down - case 53: //dodge rate up - if(i<15) - Status->Dodge_up = 0xff; - else - Status->Dodge_down = 0xff; - Stats->Dodge = GetDodge( ); - break; - case 14: //dash - case 15: //slow - case 46: //movement speed increased - if(i<15) - Status->Dash_up = 0xff; - else - Status->Dash_down = 0xff; - Stats->Move_Speed = GetMoveSpeed( ); - break; - case 16: // haste attack - case 17: // slow attack - case 47: // attack speed up - if(i<15) - Status->Haste_up = 0xff; - else - Status->Haste_down = 0xff; - Stats->Attack_Speed = GetAttackSpeed( ); - break; - case 26: // crit up - case 27: // crit down - case 52: // crit up - if(i<15) - Status->Critical_up = 0xff; - else - Status->Critical_down = 0xff; - Stats->Critical = GetCritical( ); - break; - case 12: // max HP up - case 44: // max HP up - if(i<15) - Status->HP_up = 0xff; - else - Status->HP_down = 0xff; - Stats->MaxHP = GetMaxHP( ); - break; - case 13: // max MP up - case 45: // max MP up - if(i<15) - Status->MP_up = 0xff; - else - Status->MP_down = 0xff; - Stats->MaxMP = GetMaxMP( ); - break; - case 32: // faint - Status->Stuned = 0xff; - Status->CanAttack = true; - //printf("removing stun\n"); - break; - case 7: case 8: case 9: case 10: case 11: //poisoned - Status->Poisoned = 0xff; - //printf("removing poison\n"); - break; - case 30: // muted - Status->Muted = 0xff; - Status->CanCastSkill = true; - break; - case 31: // sleep May need to be fixed later to accomodate multiple status effects. - Status->Sleep = 0xff; - Status->CanMove = true; - Status->CanCastSkill = true; - Status->CanAttack = true; - break; - case 54: //A_GMExtra_Damage: - case 36: //A_Extra_Damage: - if(i<15) - { - Status->ExtraDamage_up = 0xff; - Stats->ExtraDamage = 0xff; - } - else - { - Status->ExtraDamage_down = 0xff; - Stats->ExtraDamage = 0xff; - } - - break; - case 56: // Taunt - Status->Taunt = 0xff; - break; - } - - MagicStatus[i].Status = 0; - MagicStatus[i].Buff = 0; - MagicStatus[i].BuffTime = 0; - MagicStatus[i].Duration = 0; - MagicStatus[i].Value = 0; - bflag = true; - } - else if (MagicStatus[i].Status >= 7 && MagicStatus[i].Status <= 11 && etime > 1*CLOCKS_PER_SEC) //Do poison dmg every 1.5 seconds - { - Stats->HP -= MagicStatus[i].Status; //Actually take 7, 8, 9, 10 or 11 from the health. Based on the Status itself - MagicStatus[i].BuffTime += 1*CLOCKS_PER_SEC; - MagicStatus[i].Duration -= 1; - //printf("did %i poison dmg to the player, still %i seconds and %i HP remain \n", MagicStatus[i].Status, MagicStatus[i].Duration, Stats->HP); - - //A bunch of messy code to send dmg packet - BEGINPACKET( pak, 0x7b6 ); - ADDWORD ( pak, clientid ); - ADDWORD ( pak, 0 ); - ADDDWORD ( pak, 0x000007f8 ); - ADDBYTE ( pak, 0x00 ); - ADDDWORD ( pak, MagicStatus[i].Status ); - - //If Enemy is killed - if( IsDead()) - { - //printf("char died\n"); - CDrop* thisdrop = NULL; - ADDDWORD ( pak, 16 ); - if( !IsSummon( ) && !IsPlayer( )) - { - thisdrop = GetDrop( ); - if( thisdrop!=NULL) - { - ADDFLOAT ( pak, thisdrop->pos.x*100 ); - ADDFLOAT ( pak, thisdrop->pos.y*100 ); - if( thisdrop->type==1) - { - ADDDWORD( pak, 0xccccccdf ); - ADDDWORD( pak, thisdrop->amount ); - } - else - { - ADDDWORD ( pak, GServer->BuildItemHead( thisdrop->item ) ); - ADDDWORD ( pak, GServer->BuildItemData( thisdrop->item ) ); - } - ADDWORD ( pak, thisdrop->clientid ); - ADDWORD ( pak, thisdrop->owner ); - CMap* map = GServer->MapList.Index[thisdrop->posMap]; - map->AddDrop( thisdrop ); - } - } - GServer->SendToVisible( &pak, this, thisdrop ); - } - - //If enemy is still alive - else - { - ADDDWORD ( pak, 4 ); - GServer->SendToVisible( &pak, this ); - } - } - } - if(bflag) - { - BEGINPACKET( pak,0x7b7 ); - ADDWORD ( pak, clientid ); - ADDDWORD ( pak, GServer->BuildBuffs( this ) ); - GServer->SendToVisible( &pak, this ); - } -} - -// VIRTUAL [return party pointer] -CParty* CCharacter::GetParty( ) -{ - return NULL; -} - -// VIRTUAL [return clan pointer] -CLAN* CCharacter::GetClan( ) -{ - return NULL; -} - -bool CCharacter::IsAttacking( ) -{ - if(IsOnBattle( )) - { - switch(Battle->atktype) - { - case SKILL_BUFF: - case BUFF_SELF: - case BUFF_AOE: - return false; - } - } - else return false; - return true; -} diff --git a/Src/World Server/aip/AiActions.cpp.bak b/Src/World Server/aip/AiActions.cpp.bak deleted file mode 100644 index 556660d..0000000 --- a/Src/World Server/aip/AiActions.cpp.bak +++ /dev/null @@ -1,1472 +0,0 @@ -// Props to ExJam for this code :D -#include "../WorldServer.h" - -// extern CRandomMersenne rg; - -//Stop all actions -AIACT(000) -{ - //SetCMD_Stop (Stop all actions i guess?) - //entity->StopAll(); - CMonster* monster = reinterpret_cast(entity); - ClearBattle( monster->Battle ); - monster->Position->destiny = monster->Position->current; - return AI_SUCCESS; -} - -//Do Action -AIACT(001) -{ - //byte cAction; //Pos: 0x00 - //CObjMOB::Set_EMOTION (pak 781) - GETAIACTDATA(001); - BEGINPACKET( pak, 0x781 ); - ADDWORD ( pak, data->cAction ); - ADDWORD ( pak, 0); - ADDWORD ( pak, entity->clientid ); - GServer->SendToVisible(&pak, entity,NULL ); - return AI_SUCCESS; -} - -//Say LTB String -AIACT(002) -{ - //Client side say text - //Log(MSG_DEBUG, "Say LTB String"); - //dword iStrID; Pos: 0x00 - GETAIACTDATA(002); - - //Think this is crashing the server. Taken out for the time being. - //lets have the NPC also say the LTB string over the regular message system. This will show up green ^-^ - //CMonster* thisMonster = reinterpret_cast(entity); - //if(thisMonster->CharType == TNPC) // check if it is an NPC and not a normal monster. - //{ - // BEGINPACKET( pak, 0x0784 ); - // ADDSTRING( pak, GServer->Ltbstring[data->iStrID].NPCname ); - // ADDBYTE( pak, 0 ); - // ADDSTRING( pak, GServer->Ltbstring[data->iStrID].LTBstring ); - // ADDBYTE( pak, 0 ); - // GServer->SendToVisible(&pak, thisMonster); - //} - return AI_SUCCESS; -} - -//Move (1) -AIACT(003) -{ - //dword iDistance; //Pos: 0x00 - //byte cSpeed; //Pos: 0x04 - //move randomly within iDistance (individual x and y so its within a square) - GETAIACTDATA(003); - CMonster* monster = reinterpret_cast(entity); - monster->UpdatePosition( ); - int iDist = data->iDistance;// * 2;//Get it to our coord system! - //srand(time(NULL)); - int randDis = rand()%(iDist << 1); - float nX = (entity->Position->current.x + randDis) - iDist; - entity->Position->destiny.x=nX; - //srand(time(NULL)); - randDis = rand()%(iDist << 1); - float nY = (entity->Position->current.y + randDis) - iDist; - entity->Position->destiny.y = nY; - monster->Stats->stance = data->cSpeed; - monster->SetStats(); - entity->Position->lastMoveTime = clock(); - //ClearBattle( entity->Battle );// this also seems to clear the attackers battle?? - entity->Battle->atktype=0; - BEGINPACKET( pak, 0x797 ); - ADDWORD ( pak, entity->clientid ); - ADDWORD ( pak, 0x0000 ); - ADDWORD ( pak, entity->Stats->Move_Speed ); //speed - ADDFLOAT ( pak, entity->Position->destiny.x*100 ); - ADDFLOAT ( pak, entity->Position->destiny.y*100 ); - ADDWORD ( pak, 0xcdcd ); - ADDBYTE ( pak, monster->Stats->stance ); - GServer->SendToVisible(&pak, entity); - //Log(MSG_DEBUG, "move1 stance %i",data->cSpeed); - //Log(MSG_DEBUG, "move(1)"); - return AI_SUCCESS; -} - -//Move (2) -AIACT(004) -{ - //dword iDistance; //Pos: 0x00 - //byte cSpeed; //Pos: 0x04 - //move randomly within iDistance of spawn position (square) Position->source - GETAIACTDATA(004); - CMonster* monster = reinterpret_cast(entity); - monster->UpdatePosition( ); - int iDist = data->iDistance;//Get it to our coord system! - int randDis = rand()%(iDist << 1); - float nX = (monster->Position->source.x + randDis) - iDist; - monster->Position->destiny.x=nX; - //randDis = rg.IRandom(0, iDist << 1); - randDis = rand()%(iDist << 1); - float nY = (monster->Position->source.y + randDis) - iDist; - monster->Position->destiny.y=nY; - monster->Stats->stance = data->cSpeed; - monster->SetStats(); - monster->Position->lastMoveTime = clock(); - //ClearBattle( entity->Battle );// this also seems to clear the attackers battle?? - entity->Battle->atktype = 0; - BEGINPACKET( pak, 0x797 ); - ADDWORD ( pak, entity->clientid ); - ADDWORD ( pak, 0x0000 );//??? - ADDWORD ( pak, monster->Stats->Move_Speed ); //speed - ADDFLOAT ( pak, monster->Position->destiny.x*100 ); - ADDFLOAT ( pak, monster->Position->destiny.y*100 ); - ADDWORD ( pak, 0xcdcd ); - ADDBYTE ( pak, monster->Stats->stance ); - GServer->SendToVisible(&pak, entity); - //Log(MSG_DEBUG, "move2 stance %i",data->cSpeed); - - return AI_SUCCESS; -} - -//Move (3) -AIACT(005) -{ - //byte cSpeed; //Pos: 0x00 - //move randomly within 200 of "m_pFindCHAR" (square) - GETAIACTDATA(005); - if(entity->findChar == NULL) - return AI_FAILURE; - CMonster* monster = reinterpret_cast(entity); - monster->UpdatePosition( ); - entity->findChar->UpdatePosition(); - - int iDist = 2;//Get it to our coord system! - - - int randDis = rand()%(iDist << 1); - float nX = (entity->findChar->Position->current.x + randDis) - iDist; - entity->Position->destiny.x=nX; - - - randDis = rand()%(iDist << 1); - float nY = (entity->findChar->Position->current.y + randDis) - iDist; - entity->Position->destiny.y=nY; - monster->Stats->stance = data->cSpeed; - monster->SetStats(); - //entity->MoveTo(nX, nY); - //entity->Position->lastMoveTime = clock(); - //ClearBattle( entity->Battle );// this also seems to clear the attackers battle?? - entity->Battle->atktype = 0; - BEGINPACKET( pak, 0x797 ); - ADDWORD ( pak, entity->clientid ); - ADDWORD ( pak, 0x0000 );//??? - ADDWORD ( pak, monster->Stats->Move_Speed ); //speed - ADDFLOAT ( pak, monster->Position->destiny.x*100 ); - ADDFLOAT ( pak, monster->Position->destiny.y*100 ); - ADDWORD ( pak, 0xcdcd ); - ADDBYTE ( pak, monster->Stats->stance ); - GServer->SendToVisible(&pak, entity); - // Log(MSG_DEBUG, "move3 stance %i",data->cSpeed); - // Log(MSG_DEBUG, "move (3)"); - // RESETPACKET(pak, 0x783); - // ADDWORD(pak,entity->findChar->clientid);//entity->clientid); - // ADDSTRING(pak,"hello there"); - // ADDBYTE(pak,0); - // GServer->SendToVisible(&pak, entity); - // server->SendPacketToZone(entity, &pakout); - - return AI_SUCCESS; -} - -//Move (?) -AIACT(006) -{ - //dword iDistance; //Pos: 0x00 - //byte cAbType; //Pos: 0x04 - //byte cMoreLess; //Pos: 0x05 - //Run and Attack aiobj within iDistance that has the lowest or greatest cAbType - //cAbType - //0 = Level - //1 = Attack - //2 = Defense - //3 = "Res"? Magic Resistance? - //4 = HP - //5 = Charm - GETAIACTDATA(006); - - dword eCount = 0; - int highestAB = -9999999; - // CWorldEntity* highestEntity = NULL; - int lowestAB = 9999999; - // CWorldEntity* lowestEntity = NULL; - CMonster* monster = reinterpret_cast(entity); - if(monster->thisnpc->aggresive == 0) - return AI_FAILURE; //monster has no agression value so cannot attack a player - int aggro = GServer->RandNumber(1,20); - if(aggro > monster->thisnpc->aggresive) - return AI_FAILURE; // failed aggresiveness check - CMap* map= GServer->MapList.Index[entity->Position->Map]; - CCharacter* Target = NULL; - for(UINT i=0;iPlayerList.size();i++) - { - CPlayer* player = map->PlayerList.at(i); - if(player == NULL)continue; - if(GServer->IsMonInCircle( monster->Position->current, player->Position->current, data->iDistance)) - { - switch(data->cAbType) - { - case 0: //level - if(data->cMoreLess == 0) - { - if(player->Stats->Level > lowestAB) - { - lowestAB = player->Stats->Level; - Target = player; - }else continue; - }else{ - if(player->Stats->Level < highestAB) - { - highestAB = player->Stats->Level; - Target = player; - }else continue; - } - break; - case 1: //Attack power - if(data->cMoreLess == 0) - { - if(player->Stats->Attack_Power > lowestAB) - { - lowestAB = player->Stats->Attack_Power; - Target = player; - }else continue; - }else{ - if(player->Stats->Attack_Power < highestAB) - { - highestAB = player->Stats->Attack_Power; - Target = player; - }else continue; - } - break; - case 2: //defense - if(data->cMoreLess == 0) - { - if(player->Stats->Defense> lowestAB) - { - lowestAB = player->Stats->Defense; - Target = player; - }else continue; - }else{ - if(player->Stats->Defense < highestAB) - { - highestAB = player->Stats->Defense; - Target = player; - }else continue; - } - break; - case 3: //Magic Def - if(data->cMoreLess == 0) - { - if(player->Stats->Magic_Defense> lowestAB) - { - lowestAB = player->Stats->Magic_Defense; - Target = player; - }else continue; - }else{ - if(player->Stats->Magic_Defense < highestAB) - { - highestAB = player->Stats->Magic_Defense; - Target = player; - }else continue; - } - break; - case 4: // HP - if(data->cMoreLess == 0) - { - if(player->Stats->HP> lowestAB) - { - lowestAB = player->Stats->HP; - Target = player; - }else continue; - }else{ - if(player->Stats->HP < highestAB) - { - highestAB = player->Stats->HP; - Target = player; - }else continue; - } - break; - case 5: // Charm - if(data->cMoreLess == 0) - { - if(player->Attr->Cha > lowestAB) - { - lowestAB = player->Attr->Cha; - Target = player; - }else continue; - }else{ - if(player->Attr->Cha < highestAB) - { - highestAB = player->Attr->Cha; - Target = player; - }else continue; - } - break; - default: - break; - } - } - } - // OK we found the new Target player. now attack him. - monster->Stats->stance = 1; - monster->SetStats(); - monster->StartAction( Target, NORMAL_ATTACK, 0 ); - - // int searchDistance = data->iDistance * 100; - - // CWorldEntity** entityList = entity->thisZone->GetEntityList(); - // dword entityCount = entity->thisZone->GetEntityCount(); - // for(dword i = 1; i < MAX_ZONE_CLIENTID; i++){ - // CWorldEntity* other = entityList[i]; - // if(eCount >= entityCount) break; - // if(other == NULL) continue; - // eCount++; - // if(other == entity) continue; - // if(other->_EntityType == ENTITY_NO_TYPE) continue; - // if(other->_EntityType == ENTITY_DROP) continue; - - // int dX = (int)abs((int)other->curBlock.x - (int)entity->curBlock.x); - // if(dX > 1) continue; - // int dY = (int)abs((int)other->curBlock.y - (int)entity->curBlock.y); - // if(dY > 1) continue; - - // int iDistance = other->basic.pos.distance(entity->basic.pos); - // if(iDistance > searchDistance) continue; - - // int value = AI_GetAbility(other, data->cAbType); - - // if(value < lowestAB){ - // lowestAB = value; - // lowestEntity = other; - // } - // if(value > highestAB){ - // highestAB = value; - // highestEntity = other; - // } - // } - // if(data->cMoreLess){ - // if(lowestEntity){ - //SetCmdRUN_nATTACK - // entity->Attack(lowestEntity); - // } - // }else{ - // if(highestEntity){ - //SetCmdRUN_nATTACK - // entity->Attack(highestEntity); - // } - // } - //Log(MSG_DEBUG, "move (?)"); - return AI_SUCCESS; -} - -//Unknown -AIACT(007) -{ - //CObjCHAR::Special_ATTACK - //Log(MSG_DEBUG, "AIACT(007)"); - return AI_SUCCESS; -} - -//Move (4) -AIACT(008) -{ - //dword iDistance; //Pos: 0x00 - //byte cSpeed; //Pos: 0x04 - //Some weird shit going on here - //move within some sort of distance of target (i think possibly % iDistance of distance between target)(run away?) - //Log(MSG_DEBUG, "AIACT(008)"); - GETAIACTDATA(008); - CMonster* monster = reinterpret_cast(entity); - monster->UpdatePosition( ); - int iDist = data->iDistance;//Get it to our coord system! - float xDist = monster->Position->current.x - monster->Position->source.x; - float yDist = monster->Position->current.y - monster->Position->source.y; - float nX = monster->Position->source.x + (xDist * iDist / 100); - float nY = monster->Position->source.y + (yDist * iDist / 100); - monster->Position->destiny.x = nX; - monster->Position->destiny.y = nY; - monster->Stats->stance = data->cSpeed; - monster->SetStats(); - monster->Position->lastMoveTime = clock(); - ClearBattle( entity->Battle );// this also seems to clear the attackers battle?? - //entity->Battle->atktype = 0; - BEGINPACKET( pak, 0x797 ); - ADDWORD ( pak, entity->clientid ); - ADDWORD ( pak, 0x0000 );//??? - ADDWORD ( pak, monster->Stats->Move_Speed ); //speed - ADDFLOAT ( pak, monster->Position->destiny.x*100 ); - ADDFLOAT ( pak, monster->Position->destiny.y*100 ); - ADDWORD ( pak, 0xcdcd ); - ADDBYTE ( pak, monster->Stats->stance ); - GServer->SendToVisible(&pak, entity); - return AI_SUCCESS; -} - -//Convert Monster to new monster (1) -AIACT(009) -{ - //word wMonster; //Pos: 0x00 - //Transform into wMonster - GETAIACTDATA(009); - CMap* map= GServer->MapList.Index[entity->Position->Map]; - CMonster* monster = reinterpret_cast(entity); - int oldmon = monster->montype; - map->ConverToMonster(monster,data->wMonster,1); - //Log(MSG_DEBUG, "AIACT(009)convert monster type %i to %i",oldmon,data->wMonster); - return AI_SUCCESS; -} - -//Spawn Monster (2) -AIACT(010) -{ - //word wMonster; //Pos: 0x00 - //Spawn wMonster at current X,Y - GETAIACTDATA(010); - CMap* map = GServer->MapList.Index[entity->Position->Map]; - fPoint position; - //CMonster* newmonster; - position = GServer->RandInCircle( entity->Position->current, 1 ); - map->AddMonster( data->wMonster, position, 0, 0, 1 ); - // entity->thisZone->SpawnMonster(data->wMonster, entity->basic.pos, entity->basic.map); - //Log(MSG_DEBUG, "AIACT(010)spawn %i",data->wMonster); - return AI_SUCCESS; -} - -//Call for backup -AIACT(011) -{ - //dword iDistance; //Pos: 0x00 - //dword iNumOfMonster; //Pos: 0x04 - //force iNumOfMonster of same team within iDistance to attack my target - //CWorldEntity* target = entity->thisZone->GetEntity(entity->_TargetID); - //if(target == NULL) return AI_FAILURE; - //Log(MSG_DEBUG, "AIACT(011)"); - CCharacter* target = entity->GetCharTarget( ); - if(target == NULL) return AI_FAILURE; - GETAIACTDATA(011); - - int chrCount = 0; - dword eCount = 0; - int searchDistance = data->iDistance; - - CMap* map = GServer->MapList.Index[entity->Position->Map]; - dword entityCount = map->MonsterList.size(); - for(UINT j=0;jMonsterList.size();j++) - { - CMonster* other = map->MonsterList.at(j); - if(eCount >= entityCount) break; - if(other == NULL) continue; - eCount++; - if(other == entity) continue; - if(other->CharType != TMONSTER) continue; - - // CWorldEntity** entityList = entity->thisZone->GetEntityList(); - // dword entityCount = entity->thisZone->GetEntityCount(); - // for(dword i = 1; i < MAX_ZONE_CLIENTID; i++){ - // CWorldEntity* other = entityList[i]; - // if(eCount >= entityCount) break; - // if(other == NULL) continue; - // eCount++; - // if(other == entity) continue; - // if(other->_EntityType == ENTITY_MONSTER) continue; - // if(other->team != entity->team) continue; - // int dX = (int)abs((int)other->curBlock.x - (int)entity->curBlock.x); - // if(dX > 1) continue; - // int dY = (int)abs((int)other->curBlock.y - (int)entity->curBlock.y); - // if(dY > 1) continue; - int iDistance = (int)GServer->distance( other->Position->current, entity->Position->current ); - // int iDistance = other->basic.pos.distance(entity->basic.pos); - if(iDistance > searchDistance) continue; - chrCount++; - other->Battle->target = entity->Battle->target; - other->StartAction( (CCharacter*) target, NORMAL_ATTACK, 0 ); - - // other->Attack(target); - - if(chrCount >= data->iNumOfMonster) return AI_SUCCESS; - } - - return AI_SUCCESS; -} - -//start attack -AIACT(012) -{ - //Log(MSG_DEBUG, "AIACT(012)"); - //Run and attack "m_pNearCHAR" Nearest Character - // entity->Attack(entity->nearChar); - // Log(MSG_DEBUG, "AIACT(012)"); - if(entity->nearChar == NULL) - { - Log(MSG_DEBUG,"No target found in entity->nearchar. Now why is that?"); - return AI_FAILURE; - } - //entity->Battle->target=entity->nearChar->clientid; - CMonster* monster = reinterpret_cast(entity); - int aggro = GServer->RandNumber(1,20); - if(aggro > monster->thisnpc->aggresive) - return AI_FAILURE; // failed aggresiveness check - monster->Stats->stance = 1; - monster->SetStats(); - monster->StartAction( (CCharacter*) entity->nearChar, NORMAL_ATTACK, 0 ); - // Log(MSG_DEBUG, "AIACT(012)%i",entity->nearChar->clientid); - return AI_SUCCESS; -} - -//start attack -AIACT(013) -{ - //Log(MSG_DEBUG, "AIACT(013)"); - //Run and attack "m_pFindCHAR" Character found from aiobj loop things - // entity->Attack(entity->findChar); - if(entity->findChar == NULL) - { - Log(MSG_DEBUG,"No target found in entity->findchar. Now why is that?"); - return AI_FAILURE; - } - //entity->Battle->target=entity->findChar->clientid; - CMonster* monster = reinterpret_cast(entity); - if(monster->thisnpc->aggresive == 0) - return AI_FAILURE; //monster has no agression value so cannot attack a player - int aggro = GServer->RandNumber(1,20); - if(aggro > monster->thisnpc->aggresive) - return AI_FAILURE; // failed aggresiveness check - monster->Stats->stance = 1; - monster->SetStats(); - monster->Battle->target = entity->findChar->clientid; - monster->StartAction( (CCharacter*) entity->findChar, NORMAL_ATTACK, 0 ); - //Log(MSG_DEBUG, "AIACT(013) Monster type %i initiated combat with player %i",monster->montype, entity->findChar->clientid); - return AI_SUCCESS; -} - -//get help from other monsters -AIACT(014) -{ - //dword iDistance; //Pos: 0x00 - //find aiobj within iDistance and force them to attack my target - // CWorldEntity* target = entity->thisZone->GetEntity(entity->_TargetID); - // if(target == NULL) return AI_FAILURE; - GETAIACTDATA(014); - CMonster* monster = reinterpret_cast(entity); - CMap* map = GServer->MapList.Index[entity->Position->Map]; - CCharacter* target = entity->GetCharTarget( ); - if(target == NULL) - return AI_FAILURE; - int monstercount = 0; - for(UINT j=0;jMonsterList.size();j++) - { - CMonster* othermon = map->MonsterList.at(j); - if(othermon == NULL) - continue; - if(othermon == monster) - continue; - if(GServer->IsMonInCircle( monster->Position->current, othermon->Position->current, data->iDistance)) - { - othermon->StartAction( target, NORMAL_ATTACK, 0); - } - } - // dword eCount = 0; - // int searchDistance = data->iDistance * 100; - - // CWorldEntity** entityList = entity->thisZone->GetEntityList(); - // dword entityCount = entity->thisZone->GetEntityCount(); - // for(dword i = 1; i < MAX_ZONE_CLIENTID; i++){ - // CWorldEntity* other = entityList[i]; - // if(eCount >= entityCount) break; - // if(other == NULL) continue; - // eCount++; - // if(other == entity) continue; - // if(other->_EntityType == ENTITY_NO_TYPE) continue; - // if(other->_EntityType == ENTITY_DROP) continue; - // if(other->team != entity->team) continue; - - // int dX = (int)abs((int)other->curBlock.x - (int)entity->curBlock.x); - // if(dX > 1) continue; - // int dY = (int)abs((int)other->curBlock.y - (int)entity->curBlock.y); - // if(dY > 1) continue; - - // int iDistance = other->basic.pos.distance(entity->basic.pos); - // if(iDistance > searchDistance) continue; - - // other->Attack(target); - // return AI_SUCCESS; - // } - //Log(MSG_DEBUG, "AIACT(014)"); - return AI_SUCCESS; -} - -//Retaliate against the last character that hit me -AIACT(015) -{ - //Run and attack "m_pDestCHAR" Blah? - //Log(MSG_DEBUG, "AIACT(015)"); - CMonster* monster = reinterpret_cast(entity); - if(monster->thisnpc->aggresive == 0) - { - //Log(MSG_DEBUG, "AIACT(015) returned false as monster has no aggression"); - return AI_FAILURE; //monster has no agression value so cannot attack a player - } - if(monster->IsOnBattle()) - { - //already in battle so we don't want it switching all the time. maybe 75% of the time it will do nothing? - if(GServer->RandNumber(0,100) > 25) - { - //Log(MSG_DEBUG, "AIACT(015) returned false as we got a really bad random number %i"); - return AI_FAILURE; //denied!!! - } - if(monster->Battle->hitby == monster->Battle->target) - { - //Log(MSG_DEBUG, "AIACT(015) returned false as monster is already in combat with this player %i",monster->Battle->target); - return AI_FAILURE; //no need to initiate combat. I am already fighting this player - } - } - // otherwise change target to the person who just hit me - monster->Stats->stance = 1; - monster->SetStats(); - monster->Battle->target = monster->Battle->hitby; - CCharacter* target = entity->GetCharTarget( ); - if(target == NULL) - { - //Log(MSG_DEBUG, "I seem to have lost my target so I can't attack any more"); - return AI_FAILURE; - } - //Log(MSG_DEBUG, "Starting normal attack against opponent %i",target->clientid); - monster->StartAction( target, NORMAL_ATTACK, 0 ); - return AI_SUCCESS; -} - -//Run away -AIACT(016) -{ - //dword iDistance; - //Run Away! - //Log(MSG_DEBUG, "AIACT(016)"); - GETAIACTDATA(016); - CMonster* monster = reinterpret_cast(entity); - monster->UpdatePosition( ); - - float radius = data->iDistance; - float angle = rand()%(360); - // float angle = rg.IRandom(0,360); - // entity->UpdatePosition(); - // entity->MoveTo(entity->basic.pos.x + (radius * cos(angle)), entity->basic.pos.y + (radius * sin(angle))); - float nX = (entity->Position->source.x + (radius * cos(angle))); - entity->Position->destiny.x=nX; - float nY = (entity->Position->source.y + (radius * cos(angle))); - entity->Position->destiny.y=nY; - - monster->Stats->stance = 1; - monster->SetStats(); - - entity->Position->lastMoveTime = clock(); - //ClearBattle( entity->Battle );// this also seems to clear the attackers battle?? - entity->Battle->atktype = 0; - BEGINPACKET( pak, 0x797 ); - ADDWORD ( pak, entity->clientid ); - ADDWORD ( pak, 0x0000 );//??? - ADDWORD ( pak, entity->Stats->Move_Speed ); //speed - ADDFLOAT ( pak, entity->Position->destiny.x*100 ); - ADDFLOAT ( pak, entity->Position->destiny.y*100 ); - ADDWORD ( pak, 0xcdcd ); - ADDBYTE ( pak, 0x01 ); - GServer->SendToVisible(&pak, entity); - return AI_SUCCESS; -} - -//Drop Item -AIACT(017) -{ - //word item0; Pos: 0x00 - //word item1; Pos: 0x02 - //word item2; Pos: 0x04 - //word item3; Pos: 0x06 - //word item4; Pos: 0x08 - //word item5; pos: 0x0a dummy as a spacer - //dword btToOwner; //Pos: 0x0c - //Random drop one of item 1-5 - GETAIACTDATA(017); - //srand(time(NULL)); - int itemRand = rand()%(5); - //int itemRand = rg.IRandom(0,360); - int nItem = data->items[itemRand]; - if (nItem == 0)return AI_FAILURE; - CMonster* monster = reinterpret_cast(entity); - //CItem dropItem; - CDrop* newdrop = new (nothrow) CDrop; - newdrop->clientid = GServer->GetNewClientID( ); - newdrop->posMap = entity->Position->Map; - newdrop->pos = GServer->RandInCircle( entity->Position->current, 3 ); - newdrop->droptime = time(NULL); - if(data->btToOwner == 1) - { - newdrop->owner = monster->MonsterDrop->firsthit; - newdrop->thisparty = monster->thisparty; - } - else - { - newdrop->owner = 0; - newdrop->thisparty = 0; - } - ClearItem(newdrop->item); - newdrop->amount = 1; - newdrop->type = 2; - newdrop->item.itemnum = nItem % 1000; - newdrop->item.itemtype = nItem / 1000; - if(newdrop->item.IsStackable()) - { - newdrop->item.count = 1; - } - else - { - newdrop->item.stats = 0; - newdrop->item.durability = 40; - newdrop->item.lifespan = 1000; - newdrop->item.socketed = 0; - newdrop->item.appraised = 1; - newdrop->item.refine = 0; - } - //Log(MSG_DEBUG, "item type= %i item num = %i", newdrop->item.itemtype, newdrop->item.itemnum); - newdrop->item.count = 1; - - - CMap* map = GServer->MapList.Index[newdrop->posMap]; - map->AddDrop( newdrop ); - // entity->DropEntityItem(&dropItem); - - return AI_SUCCESS; -} - -//Make nearby monsters attack my target -AIACT(018) -{ - //word cMonster; //Pos: 0x00 - //word wHowMany; //Pos: 0x02 - //dword iDistance; //Pos: 0x04 - //make wHowMany monsters of type cMonster within iDistance attack my target - // CWorldEntity* target = entity->thisZone->GetEntity(entity->_TargetID); - // if(target == NULL) return AI_FAILURE; - GETAIACTDATA(018); - CMonster* monster = reinterpret_cast(entity); - CMap* map = GServer->MapList.Index[entity->Position->Map]; - CCharacter* target = entity->GetCharTarget( ); - if(target == NULL) - return AI_FAILURE; - int monstercount = 0; - for(UINT j=0;jMonsterList.size();j++) - { - CMonster* othermon = map->MonsterList.at(j); - if(othermon == NULL) - continue; - if(othermon == monster) - continue; - if(othermon->montype != data->cMonster) - continue; - if(GServer->IsMonInCircle( monster->Position->current, othermon->Position->current, data->iDistance)) - { - othermon->StartAction( target, NORMAL_ATTACK, 0); - monstercount++; - if(monstercount >= data->wHowMany) - return AI_SUCCESS; - } - } - // int chrCount = 0; - // dword eCount = 0; - // int nearestDistance = 9999999; - // int searchDistance = data->iDistance * 100; - - // CWorldEntity** entityList = entity->thisZone->GetEntityList(); - // dword entityCount = entity->thisZone->GetEntityCount(); - // for(dword i = 1; i < MAX_ZONE_CLIENTID; i++){ - // CWorldEntity* other = entityList[i]; - // if(eCount >= entityCount) break; - // if(other == NULL) continue; - // eCount++; - // if(other == entity) continue; - // if(other->_EntityType != ENTITY_MONSTER) continue; - // if(other->team != entity->team) continue; - // if(reinterpret_cast(other)->MonID != data->cMonster) continue; - - // int dX = (int)abs((int)other->curBlock.x - (int)entity->curBlock.x); - // if(dX > 1) continue; - // int dY = (int)abs((int)other->curBlock.y - (int)entity->curBlock.y); - // if(dY > 1) continue; - - // int iDistance = other->basic.pos.distance(entity->basic.pos); - // if(iDistance > searchDistance) continue; - // chrCount++; - - //Run and Attack target - // other->Attack(target); - - // if(chrCount >= data->wHowMany) return AI_SUCCESS; - // } - //Log(MSG_DEBUG, "AIACT(018)"); - return AI_SUCCESS; -} - -//Start attack -AIACT(019) -{ - //Run and attack "m_pNearCHAR" //Identical to 012 - return F_AI_ACT_012(server, entity, raw); -} - -//Spawn Monster (5) -AIACT(020) -{ - //word cMonster; //Pos: 0x00 - //byte btPos; //Pos: 0x02 - //dword iDistance; //Pos: 0x04 - - //Spawn cMonster within iDistance of btPos - - //btPos 0 = my pos - //btPos 1 = "m_pDestCHAR" pos - //btPos 2 = targets pos - GETAIACTDATA(020); - CMap* map = GServer->MapList.Index[entity->Position->Map]; - CMonster* monster = reinterpret_cast(entity); //need this to get the spawnid of the entity - if(monster == NULL) return AI_FAILURE; - - fPoint position; - - if(data->btPos == 0) - { - position = GServer->RandInCircle( entity->Position->current, data->iDistance ); - map->AddMonster( data->cMonster, position, 0, monster->Status->spawnid, 1 ); - } - else if(data->btPos == 1) - { - position = GServer->RandInCircle( entity->Position->current, data->iDistance ); - map->AddMonster( data->cMonster, position, 0, monster->Status->spawnid, 1 ); - //dest char - } - else if(data->btPos == 2) - { - CCharacter* target = entity->GetCharTarget( ); - if(target == NULL) return AI_FAILURE; - position = GServer->RandInCircle( target->Position->current, data->iDistance ); - map->AddMonster( data->cMonster, position, 0, monster->Status->spawnid, 1 ); - } - //Log(MSG_DEBUG, "AIACT(020)option spawn %i distance %i monstertype %i",data->btPos,data->iDistance,data->cMonster); - return AI_SUCCESS; -} - -//Unknown -AIACT(021) -{ - //Does absolutely nothing - return AI_SUCCESS; -} - -//Unknown -AIACT(022) -{ - //Does absolutely nothing - return AI_SUCCESS; -} - -//ghostseeds and ghosts and player summons commit suicide -AIACT(023) -{ - //Commit suicide - entity->Stats->HP = -1; - CMonster* thisMonster = reinterpret_cast(entity); - CMap* map = GServer->MapList.Index[entity->Position->Map]; - - BEGINPACKET( pak, 0x799 ); - ADDWORD ( pak, entity->clientid ); - ADDWORD ( pak, entity->clientid ); - ADDDWORD ( pak, 0x8005 ); - GServer->SendToVisible( &pak, entity ); - //Log(MSG_DEBUG, "AIACT(023) suicide monstertype %i",thisMonster->montype); - //thisMonster->DoAi(thisMonster->thisnpc->AI, 5); - //now release the id in the monsterlist - - //map->DeleteMonster( thisMonster); - - // something weird going on here. Client ids not being relinquished. Deletemonster does not help. it crashes the server. - - return AI_SUCCESS; -} - -//Do Skill -AIACT(024) -{ - //byte btTarget; //Pos: 0x00 - //word nSkill; //Pos: 0x02 - //word nMotion; //Pos: 0x04 //8 = SKILL_ATTACK 6 = magic - - //Use nSkill & nMotion? - //btTarget 0 = m_pFindCHAR - //btTarget 1 = target - //btTarget 2 = self skill - GETAIACTDATA(024); - // Log(MSG_DEBUG, "Do Skill btTarget %i nSkill %i nMotion %i",data->btTarget,data->nSkill,data->nMotion); - // Log(MSG_DEBUG, "entity %i",entity->clientid); - // Log(MSG_DEBUG, "entity->findChar %i",entity->findChar->clientid); - // Log(MSG_DEBUG, "entity->nearChar %i", entity->nearChar->clientid); - CSkills* thisskill = GServer->GetSkillByID( data->nSkill ); - if(thisskill == NULL)return AI_FAILURE; - CCharacter* monster = entity; - //if(monster->Battle->atktype != 0) - //{ - // Log(MSG_DEBUG,"Cannot apply battle attacktype. Monster already has one"); - // return AI_FAILURE; - //} - //Log(MSG_DEBUG,"AIACT(024)skill attack id: %i target: %i type: %i btTarget: %i nMotion: %i", data->nSkill, thisskill->target, thisskill->skilltype, data->btTarget, data->nMotion); - switch (thisskill->skilltype) - { - case 3: //damage action - case 6: //magic attack - { - CCharacter* target = entity->GetCharTarget( ); - //Log(MSG_DEBUG,"SKILL_ATTACK or DAMAGE_ACTION selected"); - if(target==NULL) - { - //Log(MSG_DEBUG,"No target can be found for this skill"); - return AI_FAILURE; - } - //Log(MSG_DEBUG,"SKILL_ATTACK selected. target: %i",target->clientid); - monster->StartAction( (CCharacter*) target, SKILL_ATTACK, data->nSkill ); - } - break; - case 7: //AOE magic attack - { - CCharacter* target = entity->GetCharTarget( ); - //Log(MSG_DEBUG,"AOE_TARGET selected"); - if(target == NULL) - { - //Log(MSG_DEBUG,"No target can be found for this skill"); - return AI_FAILURE; - } - //Log(MSG_DEBUG,"AOE_TARGET selected. target: %i",target->clientid); - monster->StartAction( (CCharacter*) target, AOE_TARGET, data->nSkill ); - } - break; - case 8: //self buff - { - //Log(MSG_DEBUG,"BUFF_SELF selected."); - monster->StartAction( NULL, BUFF_SELF, data->nSkill ); - } - break; - case 9: //skill buff - case 13://skill buff - case 11: //heal - { - CCharacter* target = entity->GetCharTarget( ); - if(target == NULL) //some skills always return a NULL target here - { - if(entity->nearChar == NULL) // maybe there really is no possible target. - { - //Log(MSG_DEBUG,"No target can be found for this skill"); - return AI_FAILURE; - } - else //so we are going to have them select a NEW target (if possible) rather than return AI_FAILURE - { - //Log(MSG_DEBUG,"SKILL_BUFF type 13 selected. NEW target: %i",entity->nearChar->clientid); - CCharacter* newtarget = entity->nearChar; - if(newtarget == NULL) - return AI_FAILURE; - monster->StartAction( (CCharacter*) newtarget, SKILL_BUFF, data->nSkill ); - } - } - else - { - //Log(MSG_DEBUG,"SKILL_BUFF type %i selected. target: %i",thisskill->skilltype, target->clientid); - monster->StartAction( (CCharacter*) target, SKILL_BUFF, data->nSkill ); - } - } - break; - case 10: //heal AOE centered on self - //Log(MSG_DEBUG,"BUFF_AOE selected. Skill id %i", data->nSkill); - monster->StartAction( NULL, BUFF_AOE, data->nSkill ); - break; - case 17: //skill AOE centered on self - { - //Log(MSG_DEBUG,"SKILL_AOE selected. Skill id %i", data->nSkill); - monster->StartAction( NULL, SKILL_AOE, data->nSkill ); - } - break; - default: - { - //Log(MSG_WARNING,"Skill type not recognized. type: %i",thisskill->skilltype); - } - break; - } - /* - if (data->btTarget == 0) - { - //CCharacter* target = entity->GetCharTarget(); - //if(target==NULL)return AI_FAILURE; - //CCharacter* monster = entity; //defined twice???? - Log(MSG_DEBUG,"BUFF_AOE selected"); - monster->StartAction( NULL, BUFF_AOE, data->nSkill ); - } - else if (data->btTarget == 1) - { - CCharacter* target = entity->GetCharTarget( ); - if(target==NULL)return AI_FAILURE; - if(data->nMotion == 8) - { - Log(MSG_DEBUG,"SKILL_ATTACK selected"); - monster->StartAction( (CCharacter*) target, SKILL_ATTACK, data->nSkill ); - } - else - { - Log(MSG_DEBUG,"SKILL_BUFF selected"); - monster->StartAction( (CCharacter*) target, SKILL_BUFF, data->nSkill ); - } - } - else if (data->btTarget == 2) - { - if(thisskill->target == tYourself) - { - Log(MSG_DEBUG,"BUFF_SELF selected"); - monster->StartAction( entity, BUFF_SELF, data->nSkill ); - } - else if (thisskill->target == tAlly) - { - Log(MSG_DEBUG,"BUFF_AOE selected"); - monster->StartAction( NULL, BUFF_AOE, data->nSkill ); - } - else if (thisskill->target == tHostileCharacter) - { - CCharacter* target = entity->GetCharTarget( ); - if(target == NULL)return AI_FAILURE; - if(data->nMotion == 8) - { - Log(MSG_DEBUG,"SKILL_ATTACK selected"); - monster->StartAction( (CCharacter*) target, SKILL_ATTACK, data->nSkill ); - } - else - { - monster->StartAction( (CCharacter*) target, SKILL_BUFF, data->nSkill ); - } - } - }*/ - return AI_SUCCESS; -} - -//Set Variable (1) -AIACT(025) -{ - // if(entity->_EntityType != ENTITY_NPC) return AI_FAILURE; - //byte btVarIDX Pos: 0x00 - //dword iValue Pos: 0x04 - //byte btOp Pos: 0x08 - GETAIACTDATA(025); - CMonster* monster = reinterpret_cast(entity); - if(monster == NULL) return AI_FAILURE; - if(data->btVarIDX > 19) return AI_FAILURE; - short tempval = GServer->ObjVar[monster->thisnpc->refNPC][data->btVarIDX]; - switch(data->btOp) - { - case 5: - tempval = data->iValue; - break; - case 6: - tempval += data->iValue; - break; - case 7: - tempval -= data->iValue; - break; - case 9: - tempval++; - break; - default: - return AI_FAILURE; - break; - } - if(tempval < 0)tempval = 0; - GServer->ObjVar[monster->thisnpc->refNPC][data->btVarIDX] = tempval; - if(data->btVarIDX == 0) //changing index 0 changes event variable at client too. Possible others too but for now just 0 - { - //Log(MSG_DEBUG,"AIACT(025) eventID has changed from %i to %i",monster->thisnpc->eventid,tempval); - monster->thisnpc->eventid = tempval; - } - return AI_SUCCESS; -} - -//Set Variable (2) -AIACT(026) -{ - //Set WorldVAR - //word nVarNo; //Pos: 0x00 - //dword iValue; //Pos: 0x04 - //byte btOp; //Pos: 0x08 - GETAIACTDATA(026); - switch(data->nVarNo) - { - case 1: - GServer->Config.EXP_RATE = data->iValue; - return AI_SUCCESS; - break; - default: - return AI_SUCCESS; - break; - } -} - -//Set Variable (3) -AIACT(027) -{ - //Set EconomyVAR - //word nVarNo; //Pos: 0x00 - //dword iValue; //Pos: 0x04 - //byte btOp; //Pos: 0x08 - return AI_SUCCESS; -} - -//Shout/Ann LTB String -AIACT(028) -{ - GETAIACTDATA(028); - //byte btMsgType Pos: 0x00 - //dword iStrID Pos: 0x04 - dword npcId = 0; - //if(entity->_EntityType == ENTITY_NPC) - CMonster* thisMonster = reinterpret_cast(entity); - switch(data->btMsgType) - { - case 0: //whisper to client - // don't think this is possible. No way to get a character to send it to?? - break; - case 1: //shout to map - //Log(MSG_INFO,"AI -- NPC Shouts to map %i",entity->Position->Map); - GServer->NPCShout(entity->Position->Map,GServer->Ltbstring[data->iStrID].LTBstring,GServer->Ltbstring[data->iStrID].NPCname); - break; - case 2: //announce to server. - GServer->NPCAnnounce(GServer->Ltbstring[data->iStrID].LTBstring,GServer->Ltbstring[data->iStrID].NPCname); - break; - default: - break; - } - - //npcId = reinterpret_cast(entity)->NpcID; - // }else if(entity->_EntityType == ENTITY_MONSTER){ - // npcId = reinterpret_cast(entity)->MonID; - // }else{ - // return AI_FAILURE; - // } - // std::map::iterator triggerITR = server->NpcNames.find(npcId); - // if(triggerITR == server->NpcNames.end()) return AI_FAILURE; - - // char* npcName = triggerITR->second; - // char* sayStr = server->lngAi->Data(data->iStrID, 1); - // if(sayStr == NULL) return AI_FAILURE; - // if(data->btMsgType == 0){ - //Chat - // CPacket pakout(0x783); - // pakout.Add(entity->_ClientID); - // pakout.Add(sayStr); - // server->SendPacketToZone(entity, &pakout); - // }else if(data->btMsgType == 1){ - //Shout - // CPacket pakout(0x785); - // pakout.Add(npcName); - // pakout.Add(sayStr); - // server->SendPacketToZone(entity, &pakout); - // }else if(data->btMsgType == 2){ - //Announce - // CPacket pakout(0x702); - // pakout.AddBytes((byte*)npcName, strlen(npcName)); - // pakout.Add('>'); - // pakout.Add(sayStr); - // server->SendPacketToZone(entity, &pakout); - // } - // delete [] sayStr; - //Log(MSG_DEBUG, "AIACT(028)"); - return AI_SUCCESS; -} - -//Move to my owner's location -AIACT(029) -{ - //Move within 20% of the distance of my "CALLER" - GETAIACTDATA(029); - // if(entity->_EntityType != ENTITY_MONSTER) return AI_FAILURE; - // CMonster* thisMonster = reinterpret_cast(entity); - // CWorldEntity* caller = thisMonster->thisZone->GetEntity(thisMonster->_CallerID); - // if(caller == NULL) return AI_FAILURE; - // caller->UpdatePosition(); - // thisMonster->UpdatePosition(); - if(!entity->IsMonster( )) return AI_FAILURE; - CMonster* thisMonster = reinterpret_cast(entity); - CMap* map = GServer->MapList.Index[thisMonster->Position->Map]; - CCharacter* caller = map->GetCharInMap( thisMonster->owner ); - if(caller == NULL) return AI_FAILURE; - caller->UpdatePosition(); - thisMonster->UpdatePosition(); - thisMonster->Stats->stance = 1; - thisMonster->SetStats(); - thisMonster->Position->source = caller->Position->current; - int iDist = GServer->RandNumber(5, 20); //move to between 5% and 20% of owners position - float xDist = thisMonster->Position->current.x - thisMonster->Position->source.x; - float yDist = thisMonster->Position->current.y - thisMonster->Position->source.y; - float nX = thisMonster->Position->source.x + (xDist * iDist / 100); - float nY = thisMonster->Position->source.y + (yDist * iDist / 100); - thisMonster->Position->destiny.x = nX; - thisMonster->Position->destiny.y = nY; - thisMonster->Position->lastMoveTime = clock(); - ClearBattle( thisMonster->Battle );// this also seems to clear the attackers battle?? - //entity->Battle->atktype = 0; - BEGINPACKET( pak, 0x797 ); - ADDWORD ( pak, entity->clientid ); - ADDWORD ( pak, 0x0000 );//??? - ADDWORD ( pak, thisMonster->Stats->Move_Speed ); //speed - ADDFLOAT ( pak, thisMonster->Position->destiny.x*100 ); - ADDFLOAT ( pak, thisMonster->Position->destiny.y*100 ); - ADDWORD ( pak, 0xcdcd ); - ADDBYTE ( pak, thisMonster->Stats->stance ); - GServer->SendToVisible(&pak, entity); - - return AI_SUCCESS; -} - -//Do Trigger -AIACT(030) -{ - //word lenszTrigger; //Pos: 0x00 - //char* szTrigger; //Pos: 0x02 - GETAIACTDATA(030); - char* tempName = reinterpret_cast(&data->szTrigger) - 2; - dword hash = MakeStrHash(tempName); - //Log(MSG_INFO, "Execute Quest Trigger %s[%d] [%08x]", tempName, data->lenszTrigger, hash); - //make a dummy player from this monster - CClientSocket* thisclient = new CClientSocket; - CPlayer* player = new CPlayer( thisclient ); - if(player == NULL) - { - Log(MSG_INFO, "Player not found in AIACT 30"); - return AI_FAILURE; - } - thisclient->player = (void*) player; - player->Position = entity->Position; - - int quest = player->ExecuteQuestTrigger(hash); - if(quest == QUEST_SUCCESS) - return AI_SUCCESS; - return AI_FAILURE; -} - -//set monster's attack target to the same as the owner -AIACT(031) -{ - //Log(MSG_DEBUG, "AIACT(031)"); - //Attack my "CALLER"(s target) if he is not an ally (must be caller's target...) - if(!entity->IsMonster( )) return AI_FAILURE; - CMonster* thisMonster = reinterpret_cast(entity); - CMap* map = GServer->MapList.Index[thisMonster->Position->Map]; - CCharacter* caller = map->GetCharInMap( thisMonster->owner ); - if(caller == NULL) return AI_FAILURE; - thisMonster->Position->source = caller->Position->current; - CCharacter* target = map->GetCharInMap(caller->Battle->target); - if(target == NULL) return AI_FAILURE; - // need to prevent the summon from attacking other summons of the same player - CMonster* otherMonster = reinterpret_cast(target); - if(otherMonster->owner == thisMonster->owner) return AI_FAILURE; - thisMonster->StartAction( (CCharacter*) target, NORMAL_ATTACK, 0 ); - //Log(MSG_DEBUG, "AIACT(031) summon attacking player's target"); - - return AI_SUCCESS; -} - -//Zone (1) -AIACT(032) -{ - //word nZoneNo; //Pos: 0x00 - //byte btOnOff; //Pos: 0x02 - //Set PK Flag (btOnOff) in nZoneNo - GETAIACTDATA(032); - //Log(MSG_DEBUG, "AIACT(032) zone (1)"); - return AI_SUCCESS; -} - -//Zone (2) -AIACT(033) -{ - //word nZoneNo //if 0, current map - //word nNewValue - //if nNewValue == 2 -> toggle - //else set regen system nNewValue (0 = off, 1 = on) - GETAIACTDATA(033); - //Log(MSG_DEBUG, "AIACT(033) zone (2)"); - return AI_SUCCESS; -} - -//Item (?) -AIACT(034) -{ - //word nItemNum; //Pos: 0x00 - //word nCount; //Pos: 0x02 - //Give item to "CALLER" - GETAIACTDATA(034); - if(!entity->IsMonster( )) return AI_FAILURE; - CMonster* thisMonster = reinterpret_cast(entity); - CMap* map = GServer->MapList.Index[thisMonster->Position->Map]; - CPlayer* caller = map->GetPlayerInMap( thisMonster->owner); - if(caller == NULL) return AI_FAILURE; - int nItem = data->nItemNum; - if (nItem == 0)return AI_FAILURE; - char itemtypes[15] = {4,0,0,0,0,0,0,0,0,0,1,2,2,4,3}; - CItem thisitem; - thisitem.Clear(); - thisitem.itemtype = nItem / 1000; - thisitem.itemnum = nItem % 1000; - thisitem.count = data->nCount; - if( itemtypes[thisitem.itemtype] == 0 ) - { - thisitem.appraised = true; - thisitem.lifespan = 100; - thisitem.gem = 0; - thisitem.durability = GServer->STB_ITEM[thisitem.itemtype-1].rows[thisitem.itemnum][29]; - } - int thisslot = caller->AddItem( thisitem ); - //Log(MSG_DEBUG,"Item type = %i item ID = %i Count = %i Slot = %i",thisitem.itemtype,thisitem.itemnum,thisitem.count,thisslot); - if (thisslot == 0xffff) // Fail - { - BEGINPACKET( pak, 0x7a7); - ADDWORD(pak, 0x00); - ADDBYTE(pak, 0x03); - ADDBYTE(pak, 0x00); - caller->client->SendPacket(&pak); - return AI_FAILURE; - } - else // Success - { - BEGINPACKET( pak, 0x71f); - ADDBYTE(pak, 0x01); - ADDBYTE(pak, thisslot); - ADDWORD(pak, caller->items[thisslot].GetPakHeader( ) ); - ADDDWORD(pak, caller->items[thisslot].GetPakData( ) ); - caller->client->SendPacket(&pak); - } - //Log(MSG_DEBUG, "AIACT(034) Item (?)"); - return AI_SUCCESS; -} - -//Set Variable (4) -AIACT(035) -{ - //Set AiVAR - //word nVarIDX; Pos: 0x00 - //dword iValue; Pos: 0x04 - //byte btOp; Pos: 0x08 - GETAIACTDATA(035); - CMonster* thisMonster = reinterpret_cast(entity); - if(data->nVarIDX >19)return AI_FAILURE; - int tempval = thisMonster->AIVar[data->nVarIDX]; - switch(data->btOp) - { - case 6: - tempval += data->iValue; - break; - case 7: - tempval -= data->iValue; - if(tempval <= 0) - { - thisMonster->AIVar[data->nVarIDX] = 0; - return AI_FAILURE; - } - break; - case 9: - tempval++; - break; - default: - return AI_FAILURE; - break; - } - thisMonster->AIVar[data->nVarIDX] = tempval; - //thisMonster->thisnpc->Objvar->SetVar(data->btOp, data->iValue); //code not working - return AI_SUCCESS; -} - -//Monster (1) -AIACT(036) -{ - //word nMonster; //Pos: 0x00 - //byte btMaster; //Pos: 0x02 - //Spawn nMonster at my position (has btMaster)? - GETAIACTDATA(036); - // CWorldEntity* master = NULL; - // if(data->btMaster) master = entity; - CMonster* monster = reinterpret_cast(entity); //need this to get the spawnid of the entity - CMap* map = GServer->MapList.Index[entity->Position->Map]; - int owner = 0; - if(data->btMaster == 1) - owner = monster->clientid; - map->AddMonster( data->nMonster, entity->Position->current, 0, monster->Status->spawnid, 10 ); - //Log(MSG_DEBUG, "AIACT(36) monster (1) no code here"); - return AI_SUCCESS; -} - -//Monster (2) -AIACT(037) -{ - //word nMonster; //Pos: 0x00 - //word nPos; //Pos: 0x02 - //dword iDistance; //Pos: 0x04 - //byte btMaster; //Pos: 0x08 - - //Spawn nMonster at nPos within iDistance (has btMaster)? - //nPos = 0 my pos - //nPos = 1 m_pDestCHAR pos - //nPos = 2 target pos - GETAIACTDATA(037); - CMap* map = GServer->MapList.Index[entity->Position->Map]; - CMonster* monster = reinterpret_cast(entity); //need this to get the spawnid of the entity - if(monster == NULL) return AI_FAILURE; - int owner = 0; - if(data->btMaster == 1) - owner = monster->clientid; - fPoint position; - - if(data->nPos == 0) //spawn monster in a circle with radius iDistance around my current position - { - position = GServer->RandInCircle( entity->Position->current, data->iDistance ); - map->AddMonster( data->nMonster, position, 0, monster->Status->spawnid, 10 ); - } - else if(data->nPos == 1) //spawn monster in a circle with radius iDistance around my destiny position - { - position = GServer->RandInCircle( entity->Position->destiny, data->iDistance ); - map->AddMonster( data->nMonster, position, 0, monster->Status->spawnid, 10 ); - //dest char - } - else if(data->nPos == 2) //spawn monster in a circle with radius iDistance around my target's current position - { - CCharacter* target = entity->GetCharTarget( ); - if(target == NULL) return AI_FAILURE; - position = GServer->RandInCircle( target->Position->current, data->iDistance ); - map->AddMonster( data->nMonster, position, 0, monster->Status->spawnid, 10 ); - } - return AI_SUCCESS; -} - -//TDEF code. move to next waypoint -AIACT(038) -{ - //byte cSpeed pos 0x00 - GETAIACTDATA(038); - CMonster* monster = reinterpret_cast(entity); - monster->NextWayPoint ++; - monster->Position->destiny.x = GServer->WPList[monster->Position->Map][monster->NextWayPoint].X; - monster->Position->destiny.y = GServer->WPList[monster->Position->Map][monster->NextWayPoint].Y; - monster->Stats->stance = data->cSpeed; - entity->Position->lastMoveTime = clock(); - BEGINPACKET( pak, 0x797 ); - ADDWORD ( pak, entity->clientid ); - ADDWORD ( pak, 0x0000 ); - ADDWORD ( pak, entity->Stats->Move_Speed ); //speed - ADDFLOAT ( pak, monster->Position->destiny.x*100 ); - ADDFLOAT ( pak, monster->Position->destiny.y*100 ); - ADDWORD ( pak, 0xcdcd ); - ADDBYTE ( pak, monster->Stats->stance ); - GServer->SendToVisible(&pak, entity); - return AI_SUCCESS; -} diff --git a/Src/World Server/battle_old_version.cpp b/Src/World Server/battle_old_version.cpp deleted file mode 100644 index 164c132..0000000 --- a/Src/World Server/battle_old_version.cpp +++ /dev/null @@ -1,802 +0,0 @@ -/* - Rose Online Server Emulator - Copyright (C) 2006,2007 OSRose Team http://www.osrose.net - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - depeloped with Main erose/hrose source server + some change from the original eich source -*/ -#include "character.h" -#include "worldserver.h" - -void CCharacter::DoAttack( ) -{ - //if(Status->Sleep <= 0xff) - //{ - // ClearBattle( Battle ); - // return; // can't take any action while we are asleep can we? - //} - if(IsSummon()) - { - CCharacter* Enemy = GetCharTarget( ); - if(Enemy == NULL && Battle->atktype != SKILL_AOE && Battle->atktype != BUFF_AOE) - { - //Log(MSG_DEBUG,"No Enemy found"); - ClearBattle( Battle ); - return; - } - //Log(MSG_DEBUG,"Client id: %i Enemy client id: %i",clientid, Enemy->clientid); - if(this == Enemy) //summoned monster is attacking itself. It has been observed to happen - { - //Log(MSG_INFO,"Clearing Battle for this summon"); - ClearBattle( Battle ); - return; - } - } - CMap* map = GServer->MapList.Index[Position->Map]; - //Log(MSG_INFO,"DoAttack Battle Attack type = %i",Battle->atktype); - switch(Battle->atktype) - { - case NORMAL_ATTACK://normal attack - { - //if(!Status->CanAttack) - // return; //can't attack right now. - CCharacter* Enemy = GetCharTarget( ); - if(Enemy == NULL) - { - ClearBattle( Battle ); - return; - } - if(Enemy == this) - { - //Log(MSG_INFO,"WTF?? I AM trying to attack myself"); - ClearBattle( Battle ); - } - if(IsTargetReached( Enemy ) && CanAttack( )) - { - NormalAttack( Enemy ); - if (Enemy->IsMonster()) // do monster AI script when monster is attacked. - { - CMonster* monster = GServer->GetMonsterByID(Enemy->clientid, Enemy->Position->Map); - if(monster == NULL)return; - monster->DoAi(monster->thisnpc->AI, 3); - } - - } - } - break; - case SKILL_ATTACK://skill attack - { - //if(!Status->CanCastSkill) - // return; // can't cast skills right now - CCharacter* Enemy = GetCharTarget( ); - if(Enemy == NULL) - { - ClearBattle( Battle ); - return; - } - CSkills* skill = GServer->GetSkillByID( Battle->skillid ); - if(skill == NULL) - { - //ClearBattle( Battle ); - return; - } - if(IsTargetReached( Enemy, skill ) && CanAttack( )) - { - SkillAttack( Enemy, skill ); - if (Enemy->IsMonster()) - { - CMonster* monster = GServer->GetMonsterByID(Enemy->clientid, Enemy->Position->Map); - if(monster == NULL)return; - monster->DoAi(monster->thisnpc->AI, 3); - } - } - } - break; - case SKILL_BUFF://buffs - { - //if(!Status->CanCastSkill) - // return; // can't cast skills right now - CCharacter* Enemy = GetCharTarget( ); - if(Enemy == NULL) - { - //Log(MSG_DEBUG,"this target is NULL"); - ClearBattle( Battle ); - return; - } - CSkills* skill = GServer->GetSkillByID( Battle->skillid ); - if(skill == NULL) - { - //Log(MSG_DEBUG,"this skill is NULL"); - //ClearBattle( Battle ); - return; - } - //Log(MSG_DEBUG,"Called skill buff code for skill %i",skill->id); - if(IsTargetReached( Enemy, skill ) && CanAttack( )) - { - //Log(MSG_DEBUG,"Skill successfully cast"); - BuffSkill( Enemy, skill ); - } - } - break; - case SKILL_AOE: - //case SKILL_SELF: //this is impossible. it can never be set - case AOE_TARGET: - { - //if(!Status->CanCastSkill) - // return; // can't cast skills right now - //Log(MSG_DEBUG,"Called skill type %i",Battle->atktype); - CCharacter* Enemy = NULL; - CSkills* skill = GServer->GetSkillByID( Battle->skillid ); - if(skill == NULL) - { - ClearBattle( Battle ); - return; - } - if(Battle->atktype == AOE_TARGET) - { - float distance = GServer->distance( Position->current, Position->destiny ); - if(distance <= skill->range && CanAttack( )) - { - Position->destiny = Position->current; - AoeSkill( skill, Enemy ); - } - } - else - { - Position->skilltargetpos = Position->current; - AoeSkill( skill, NULL ); - } - } - break; - case BUFF_SELF: - { - //if(!Status->CanCastSkill) - // return; // can't cast skills right now - CSkills* skill = GServer->GetSkillByID( Battle->skillid ); - if(skill == NULL) - { - //ClearBattle( Battle ); - return; - } - BuffSkill( this, skill ); - } - break; - case BUFF_AOE: - { - //if(!Status->CanCastSkill) - // return; // can't cast skills right now - Log(MSG_INFO,"BUFF AOE selected"); - CSkills* skill = GServer->GetSkillByID( Battle->skillid ); - if(skill == NULL) - { - //ClearBattle( Battle ); - - return; - } - AoeBuff( skill ); - } - break; - default: - return; - break; - } -} - - -// do normal attack -void CCharacter::NormalAttack( CCharacter* Enemy ) -{ - Enemy->OnBeAttacked( this ); - Position->destiny = Position->current; - // PY code - float mod = 0; - if(IsPlayer()) - { - mod = 23 + (Stats->Level / 1.5); - } - else - { - mod = 23 + (Stats->Level / 4); - - } - float attack = 0; - if(Stats->magicattack == 1) - { - attack = (float) Stats->Attack_Power / Enemy->Stats->Magic_Defense; - attack *= mod; - } - else - { - attack = (float) Stats->Attack_Power / Enemy->Stats->Defense; - attack *= mod; - } - //PY end - if(attack < 5) attack = 5; - float d_attack = attack / 100; - mod = GServer->RandNumber( 0, 10 ) * d_attack; - attack += mod; - long int hitpower = (long int)floor(attack + GServer->RandNumber(0, 10)); - if(IsPlayer( )) //temp fix to find balance btw monster and player - { - hitpower = (long int)floor(attack * (GServer->Config.PlayerDmg/100.00)); - hitpower+=((hitpower*(Stats->ExtraDamage))/100); - } - if(IsMonster( )) //temp fix to find balance btw monster and player - hitpower = (long int)floor(attack * (GServer->Config.MonsterDmg/100.00)); - bool critical = false; - if(hitpower <= 5) - { - hitpower = 5; - } - else - { - if(GServer->RandNumber(0,300)Critical) - { - hitpower = (long int)floor(hitpower * 1.5); - critical = true; - } - } - // dodge - unsigned int hitvalue = (unsigned int)floor((double)(Stats->Accury * 100 / Enemy->Stats->Dodge)); - if(hitvalue>100) hitvalue = 100; - if(GServer->RandNumber( 0, 100 )>hitvalue) - hitpower = 0; // dodged - if (hitpower > 0x7ff)//2047 packet size limit. - { - hitpower=0x7ff; - } - - //maybe this little line here will fix my ghosty problem - //they are definitely attacking. But no animation so maybe atktarget is empty - Battle->atktarget = Battle->target; - //Well it does make the damage show up at teh client but the animation is still dodgey - - if(IsMonster()) - { - Log(MSG_INFO,"Monster hits player for %i damage. Attack target = %i",hitpower,Battle->atktarget); - } - //Log( MSG_INFO, "hitpower %i. Attack %f ", hitpower,attack ); - if(!Enemy->IsSummon( ) && Enemy->IsMonster( )) - { - Enemy->AddDamage( this, hitpower ); - Enemy->damagecounter += hitpower;// is for AI - } - Enemy->Stats->HP -= hitpower; - - - - BEGINPACKET( pak, 0x799 ); - ADDWORD ( pak, clientid ); - ADDWORD ( pak, Battle->atktarget ); -#ifdef USE124 - ADDDWORD ( pak, hitpower ); -#endif - - if(Enemy->IsDead()) - { - CDrop* thisdrop = NULL; -#ifndef USE124 - ADDWORD ( pak, (hitpower | ( critical?0xb000:0x8000 ) )); -#else - ADDDWORD ( pak, critical?28:16 ); -#endif - if(!Enemy->IsSummon( ) && !Enemy->IsPlayer( )) - { - thisdrop = Enemy->GetDrop( ); - if(thisdrop!=NULL) - { - ADDFLOAT ( pak, thisdrop->pos.x*100 ); - ADDFLOAT ( pak, thisdrop->pos.y*100 ); - if(thisdrop->type == 1) - { - ADDWORD( pak, 0xccdf ); - ADDDWORD( pak, thisdrop->amount ); - } - else - { - ADDWORD ( pak, GServer->BuildItemHead( thisdrop->item ) ); - ADDDWORD ( pak, GServer->BuildItemData( thisdrop->item ) ); - } - ADDWORD ( pak, thisdrop->clientid ); - ADDWORD ( pak, thisdrop->owner ); - CMap* map = GServer->MapList.Index[thisdrop->posMap]; - map->AddDrop( thisdrop ); - } - } - GServer->SendToVisible( &pak, Enemy, thisdrop ); - OnEnemyDie( Enemy ); - } - else - { -#ifndef USE124 - ADDWORD ( pak, (hitpower|(hitpower>0?(critical?0x4000:0):0))); -#else - ADDDWORD ( pak, (hitpower>0?(critical?12:0):0) ); -#endif - GServer->SendToVisible( &pak, Enemy ); - } - ReduceABC( ); - Battle->lastAtkTime = clock( ); -} - -// do skill attack -bool CCharacter::SkillAttack( CCharacter* Enemy, CSkills* skill ) -{ - Position->destiny = Position->current; - //if(Battle->castTime==0) - //{ - BEGINPACKET( pak, 0x7bb ); - ADDWORD ( pak, clientid ); - GServer->SendToVisible( &pak, this ); - // Battle->castTime = clock(); - // return true; - //} - //else - //{ - // clock_t etime = clock() - Battle->castTime; - // if(etimecastTime = 0; - UseAtkSkill( Enemy, skill ); - Stats->MP -= (skill->mp - (skill->mp * Stats->MPReduction / 100)); - if(Stats->MP<0) Stats->MP=0; - if(Battle->contatk) - { - Battle->atktype = NORMAL_ATTACK; - Battle->skilltarget = 0; - Battle->atktarget = Battle->target; - Battle->skillid = 0; - } - else - { - //ClearBattle( Battle ); - } - GServer->DoSkillScript( this, skill ); - Battle->lastAtkTime = clock( ); - return true; -} - -// do buff skill -bool CCharacter::BuffSkill( CCharacter* Target, CSkills* skill ) -{ - Position->destiny = Position->current; - //if(Battle->castTime == 0) - //{ - BEGINPACKET( pak, 0x7bb ); - ADDWORD ( pak, clientid ); - GServer->SendToVisible( &pak, (CCharacter*)this ); - // Battle->castTime = clock(); - // return true; - //} - //else - //{ - // clock_t etime = clock() - Battle->castTime; - // if(etime < SKILL_DELAY) - // return true; - //} - //Battle->castTime = 0; - //Log(MSG_DEBUG,"applied buff skill %i",skill->id); - UseBuffSkill( Target, skill ); - Stats->MP -= (skill->mp - (skill->mp * Stats->MPReduction / 100)); - if(Stats->MP < 0) Stats->MP = 0; - GServer->DoSkillScript( this, skill ); //summons a monster. Why do we do this for all skills? - if(!IsMonster()) - { - ClearBattle( Battle ); // clear battle for players when they use buff skills - //Battle->bufftarget = 0; - //Battle->skilltarget = 0; - //Battle->skillid = 0; - //Battle->atktype = NORMAL_ATTACK; - } - else //Monsters need to be reset to normal attack and clear skill attacks. - { - Battle->bufftarget = 0; - Battle->skilltarget = 0; - Battle->skillid = 0; - Battle->atktype = NORMAL_ATTACK; - } - Battle->lastAtkTime = clock( ); - return true; -} -//arnold -// do AoE skill -bool CCharacter::AoeSkill( CSkills* skill, CCharacter* Enemy ) -{ - Position->destiny = Position->current; - //Log(MSG_INFO,"Doing AOE Skill"); - //if(Battle->castTime == 0) - //{ - BEGINPACKET( pak, 0x7bb ); - ADDWORD ( pak, clientid ); - GServer->SendToVisible( &pak, (CCharacter*)this ); - // Battle->castTime = clock(); - // return true; - //} - //else - //{ - // clock_t etime = clock() - Battle->castTime; - // if(etime < SKILL_DELAY) - // return true; - //} - //Battle->castTime = 0; - CMap* map = GServer->MapList.Index[Position->Map]; - - //PY replacement code - if(IsPlayer() || IsSummon()) - { - for(UINT i=0;iMonsterList.size();i++) - { - CMonster* monster = map->MonsterList.at(i); - if(monster->clientid == clientid) continue; - if(monster->IsSummon( ) && (map->allowpvp == 0 || monster->owner == clientid)) continue; - if(GServer->IsMonInCircle( Position->skilltargetpos, monster->Position->current,(float)skill->aoeradius + 1)) - UseAtkSkill( (CCharacter*) monster, skill ); - } - } - if(IsMonster() && !IsSummon()) - { - for(UINT i=0;iPlayerList.size();i++) - { - CPlayer* player = map->PlayerList.at(i); - if(player->clientid == clientid) continue; - if(GServer->IsMonInCircle( Position->skilltargetpos,player->Position->current,(float)skill->aoeradius+1)) - UseAtkSkill( (CCharacter*) player, skill ); - } - } - //PY end - - // this code appears to me to be completely wrong replaced with code above - /* - for(UINT i=0;iMonsterList.size();i++) - { - CMonster* monster = map->MonsterList.at(i); - if(monster->clientid == clientid) continue; - if(IsSummon( ) || IsPlayer( )) - { - if(monster->IsSummon( ) && (map->allowpvp==0 || monster->owner == clientid)) continue; - } - else - { - if(!monster->IsSummon( )) continue; - } - if(GServer->IsMonInCircle( Position->skilltargetpos, monster->Position->current,(float)skill->aoeradius + 1)) - UseAtkSkill( (CCharacter*) monster, skill ); - } - if(map->allowpvp!=0 || (IsMonster( ) && !IsSummon( ))) - { - for(UINT i=0;iPlayerList.size();i++) - { - CPlayer* player = map->PlayerList.at(i); - if(player->clientid==clientid) continue; - if(GServer->IsMonInCircle( Position->skilltargetpos,player->Position->current,(float)skill->aoeradius+1)) - UseAtkSkill( (CCharacter*) player, skill ); - } - }*/ - - if(Enemy != NULL) - { - if(!Enemy->IsDead( )) - { - Battle->atktarget = Battle->target; - Battle->atktype = NORMAL_ATTACK; - Battle->skilltarget = 0; - Battle->skillid = 0; - } - else ClearBattle( Battle ); - } - else ClearBattle( Battle ); - Stats->MP -= (skill->mp - (skill->mp * Stats->MPReduction / 100)); - if(Stats->MP < 0) Stats->MP = 0; - Battle->lastAtkTime = clock( ); - return true; -} - -bool CCharacter::AoeBuff( CSkills* skill ) -{ - //Log(MSG_INFO,"BUFF AOE called"); - Position->destiny = Position->current; - BEGINPACKET( pak, 0x7bb ); - ADDWORD ( pak, clientid ); - GServer->SendToVisible( &pak, (CCharacter*)this ); - CMap* map = GServer->MapList.Index[Position->Map]; - - if(CharType == 1 || CharType == 3) //player || Summon - { - for(UINT i=0;iPlayerList.size();i++) - { - CPlayer* player = map->PlayerList.at(i); - switch(skill->target) - { - case 1: //tPartyMember - if(player->Party->party == GetParty( )) - { - //Log(MSG_INFO,"Applying AOE buff as long as I can find a close enough party member"); - if(GServer->IsMonInCircle( Position->current,player->Position->current,(float)skill->aoeradius + 1)) - UseBuffSkill( (CCharacter*)player, skill ); - } - break; - case 2: //tClanMember - if (player->Clan == GetClan( )) - { - //Log(MSG_INFO,"Applying AOE buff as long as I can find a close enough clan member"); - if(GServer->IsMonInCircle( Position->current, player->Position->current, (float)skill->aoeradius + 1 ) ) - UseBuffSkill( (CCharacter*)player, skill ); - } - break; - case 3: //tAlly - case 7: //tAllCharacters - case 8: //tAllMembers. all characters - { - //Log(MSG_INFO,"Applying AOE buff as long as I can find a close enough allied Player"); - if(GServer->IsMonInCircle( Position->current,player->Position->current,(float)skill->aoeradius + 1)) - UseBuffSkill( (CCharacter*)player, skill ); - } - break; - case 5: //tHostileCharacter - { - if (CharType == 2) - { - //Log(MSG_INFO,"Applying AOE buff as long as I can find a close enough hostile Player"); - if(GServer->IsMonInCircle( Position->current,player->Position->current,(float)skill->aoeradius + 1)) - UseBuffSkill( (CCharacter*)player, skill ); - } - } - break; - } - } - } - else if (CharType == 2) //monster - { - for(UINT i=0;iMonsterList.size();i++) - { - CMonster* monster = map->MonsterList.at(i); - switch(skill->target) - { - case tPartyMember: // party - break; - case 2: //tClanMember - break; - case 3: //tAlly - case 7: //tAllCharacters - case 8: //tAllMembers. all characters - { - Log(MSG_INFO,"Applying AOE buff as long as I can find a close enough monster"); - if(GServer->IsMonInCircle( Position->current,monster->Position->current,(float)skill->aoeradius + 1)) - UseBuffSkill( (CCharacter*)monster, skill ); - } - break; - case tHostileCharacter: - break; - } - } - } - Stats->MP -= (skill->mp - (skill->mp * Stats->MPReduction / 100)); - if(Stats->MP < 0) Stats->MP = 0; - Battle->bufftarget = 0; - Battle->skilltarget = 0; - Battle->skillid = 0; - Battle->atktype = NORMAL_ATTACK; - //ClearBattle( Battle ); - Battle->lastAtkTime = clock( ); - return true; -} - - - -// use skill attack -void CCharacter::UseAtkSkill( CCharacter* Enemy, CSkills* skill, bool deBuff) -{ - long int skillpower = 0; - if(skill->skilltype == 6 || skill->skilltype == 7) //magical damage - { - skillpower = skill->atkpower * 2; - } - else // physical damage - { - skillpower = skill->atkpower * 2; - } - UINT weapontype = 0; - - float mod = 0; - float attack = 0; - if(IsPlayer()) - { - mod = 35 + (Stats->Level / 2); - } - else - { - mod = 35 + (Stats->Level / 2); - } - if(skill->skilltype == 6 || skill->skilltype == 7) //magical damage - { - attack = skillpower / Enemy->Stats->Magic_Defense; - } - else - { - attack = skillpower / Enemy->Stats->Defense; - } - attack *= mod; - attack += (Stats->Attack_Power / 2); // let's add our AP to the skillpower to make it worthwhile to cast skills. - - skillpower = (int)attack; - bool bflag = false; - Enemy->OnBeAttacked( this ); - if(skillpower <= 0) skillpower = 0; - if(IsPlayer()) - { - skillpower += (int)(skillpower * (Stats->ExtraDamage))/100; - } - if (skill->atkpower == 0) - { - skillpower = 0; // If the skill has a 0 atk power, it isn't meant to damage - Log( MSG_INFO, "This skill does no damage" ); - //ClearBattle( Battle ); - return; // probably need to add some alternative code here for legitimate skills that have no attack power. - } - if(skillpower >2046)skillpower = 2046; - if(!Enemy->IsSummon( ) && Enemy->IsMonster( )) - { - Enemy->AddDamage( this, skillpower ); - Enemy->damagecounter += skillpower;// is for AI - } - Enemy->Stats->HP -= skillpower; - BEGINPACKET( pak, 0x7b6 ); - ADDWORD ( pak, Enemy->clientid ); - ADDWORD ( pak, clientid ); - ADDDWORD ( pak, 0x000007f8 ); - ADDBYTE ( pak, 0x00 ); - if (Enemy->Stats->HP<1) - { - ADDWORD ( pak, skillpower + 0x8000 ); - } - else - { - ADDWORD ( pak, skillpower + 0x2000 ); - } - if(Enemy->IsDead()) - { - CDrop* thisdrop = NULL; - ADDDWORD ( pak, 16 ); - if(!Enemy->IsSummon( ) && !Enemy->IsPlayer( )) - { - thisdrop = Enemy->GetDrop( ); - if(thisdrop!=NULL) - { - ADDFLOAT ( pak, thisdrop->pos.x*100 ); - ADDFLOAT ( pak, thisdrop->pos.y*100 ); - if(thisdrop->type==1) - { - ADDWORD( pak, 0xccdf ); - ADDDWORD( pak, thisdrop->amount ); - } - else - { - ADDWORD ( pak, GServer->BuildItemHead( thisdrop->item ) ); - ADDDWORD ( pak, GServer->BuildItemData( thisdrop->item ) ); - } - ADDWORD ( pak, thisdrop->clientid ); - ADDWORD ( pak, thisdrop->owner ); - CMap* map = GServer->MapList.Index[thisdrop->posMap]; - map->AddDrop( thisdrop ); - } - } - GServer->SendToVisible( &pak, Enemy, thisdrop ); - OnEnemyDie( Enemy ); - } - else - { - ADDDWORD ( pak, 4 ); - GServer->SendToVisible( &pak, Enemy ); - bflag = GServer->AddBuffs( skill, Enemy, GetInt( ) ); - - //Send (de)buff information to the whole world - if(skill->nbuffs>0 && bflag) - { - BEGINPACKET( pak, 0x7b5 ); - ADDWORD ( pak, Battle->skilltarget ); - ADDWORD ( pak, clientid ); - ADDWORD ( pak, Battle->skillid ); - ADDWORD ( pak, GetInt( ) ); - ADDBYTE ( pak, skill->nbuffs ); - GServer->SendToVisible( &pak, Enemy ); - } - } - if (deBuff) return; - //Send skill animation to the world - RESETPACKET( pak, 0x7b9); - ADDWORD ( pak, clientid); - ADDWORD ( pak, Battle->skillid); - ADDWORD ( pak, 1); - GServer->SendToVisible( &pak, this ); - Battle->bufftarget = 0; - Battle->skilltarget = 0; - Battle->skillid = 0; - Battle->atktype = NORMAL_ATTACK; -} - -// use buff skill -void CCharacter::UseBuffSkill( CCharacter* Target, CSkills* skill ) -{ - bool bflag = false; - bflag = GServer->AddBuffs( skill, Target, GetInt( ) ); - if(skill->nbuffs > 0 && bflag == true) - { - BEGINPACKET( pak, 0x7b5 ); - ADDWORD ( pak, Target->clientid ); - ADDWORD ( pak, clientid ); - ADDWORD ( pak, Battle->skillid ); - ADDWORD ( pak, GetInt( )/4 ); - ADDBYTE ( pak, skill->nbuffs ); - GServer->SendToVisible( &pak, Target ); - //Log(MSG_DEBUG,"Buff Skill. buffs applied 1"); - } - - BEGINPACKET( pak, 0x7b9); - ADDWORD ( pak, clientid); - ADDWORD ( pak, Battle->skillid); - ADDWORD ( pak, 1); - GServer->SendToVisible( &pak, this ); - //Log(MSG_DEBUG,"Buff Skill. buffs applied 2 nbuffs = %i",skill->nbuffs); - //Log(MSG_INFO,"Target HP = %i",Target->Stats->HP); -} - -// Use a skill -bool CCharacter::UseSkill( CSkills* skill, CCharacter *Target ) -{ - if (skill->atkpower > 0) - { - Log(MSG_INFO, "Need to do %i%s %s in range %i to target %i", - ( skill->atkpower ), - ( (skill->range > 0) ? " AOE" : "" ), - ( (GServer->isSkillTargetFriendly(skill)) ? "healing" : "damage" ), - ( skill->range ), - ( skill->target ) ); - } - for (int i = 0; i < 2; i++) { - Log(MSG_INFO, "Status ID: %i", skill->status[i]); - if (skill->status[i] == 0) continue; - CStatus* status = GServer->GetStatusByID(skill->status[i]); - if (status == NULL) continue; - /************************ - We'll probably need to use status->decrease (Figure out whether buf is up/down - status->repeat will tell us whether it's a one-time (Stat Boost [2]), repeat - (Recovery, continueing damage [1]) or Special (Status Effect [3]). - ************************/ - if (status->repeat == 1) // Continuous - { - Log(MSG_INFO, "Need to take stat %i and %s it by %i%s over %i seconds", skill->buff[i], - ((status->decrease) ? "decrease" : "increase"), - ((skill->value1[i] != 0) ? skill->value1[i] : skill->value2[i]), - ((skill->value1[i] != 0) ? "" : "%"), skill->duration); - } - else if (status->repeat == 2) // Once (Stat Boost) - { - Log(MSG_INFO, "Need to take stat %i and %s it by %i%s for %i seconds", skill->buff[i], - ((status->decrease) ? "decrease" : "increase"), - ((skill->value1[i] != 0) ? skill->value1[i] : skill->value2[i]), - ((skill->value1[i] != 0) ? "" : "%"), skill->duration); - - } else if (status->repeat == 3) // Status Effect (Poison,etc) - { - Log(MSG_INFO, "Need to give user status effect %i for %i seconds", skill->buff[i], - ((skill->value1[i] != 0) ? skill->value1[i] : skill->value2[i]), - ( skill->duration ) ); - - } - } - return true; -} \ No newline at end of file diff --git a/Src/World Server/worldmap.h.bak b/Src/World Server/worldmap.h.bak deleted file mode 100644 index 2386ab2..0000000 --- a/Src/World Server/worldmap.h.bak +++ /dev/null @@ -1,119 +0,0 @@ -/* - Rose Online Server Emulator - Copyright (C) 2006,2007 OSRose Team http://www.osrose.net - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - depeloped with Main erose/hrose source server + some change from the original eich source -*/ -#ifndef __ROSE_MAP__ -#define __ROSE_MAP__ -#include "worldserver.h" -#include "player.h" -#include "character.h" -#include "worldmonster.h" -#include "datatypes.h" -class CMonster; - -class CMap -{ - public: - CMap( ); - ~CMap( ); - - bool AddPlayer( CPlayer* player ); - bool RemovePlayer( CPlayer* player, bool clearobject=true ); - - //CMonster* AddMonster( UINT montype, fPoint position, UINT owner=0, UINT spawnid=0, bool GetDropData=false ); - CMonster* AddMonster( UINT montype, fPoint position, UINT owner=0, UINT spawnid=0, UINT aggro = 0, bool IsTD = false, UINT limit = 0, UINT AI = 0); - bool DeleteMonster( CMonster*, bool clearobject=false, UINT i=0 ); - bool AddDrop( CDrop* drop ); - bool DeleteDrop( CDrop* drop ); - bool AddNPC( CNPC* npc ); - bool DeleteNPC( CNPC* npc ); - - CMonster* ConverToMonster( CMonster* monster, UINT newmonttype, bool heal=true ); - CMonster* ConverToMonster( CNPC* npc, UINT newmonttype ); - - bool TeleportPlayer( CPlayer* player, fPoint coord, bool TelePassenger=true ); - bool pakTeleport( CPlayer* player, unsigned int Map, fPoint coord, bool TelePassenger ); - - CRespawnPoint* GetNearRespawn( CPlayer* player ); - CRespawnPoint* GetFirstRespawn( ); - CRespawnPoint* GetStartRespawn( ); - - CCharacter* GetCharInMap( unsigned int id ); - CPlayer* GetPlayerInMap( UINT id ); - CMonster* GetMonsterInMap( UINT id ); - CPlayer* GetCharIDInMap( UINT id ); - CDrop* GetDropInMap( UINT id ); - CNPC* GetNPCInMap( UINT id ); - void UpdateTime( ); - void CleanDrops( ); - void RespawnMonster( ); - void UpdateSpawnCounter( UINT montype, UINT spawnid, UINT key ); - bool IsNight( ); - - void LoadZon(strings zon); - void LoadData(strings zonpath, CStrStb* stbEvent); - void AddIfo(strings ifo, CStrStb* stbEvent); - - UINT id; // id from map - UINT dayperiod; // duration of 1 day - UINT morningtime; // morning start time - UINT daytime; // day start time - UINT eveningtime; // evening start time - UINT nighttime; // nighttime start time - UINT ZoneTime; // how many 6 minute segments since start of the day - UINT ghost; // ghosttime? - BYTE allowpvp; // pvp allowed? - bool dungeon; // Map is a dungeon? - bool allowpat; // pat allowed? - // Time values - UINT MapTime; // Past time in this map - UINT Date; - UINT hour; - UINT minute; - UINT ObjVar[20]; //for storing map variables used in AIP - clock_t LastUpdate;// Last time update in the map - UINT CurrentTime; // 0 = morning | 1 = day | 2 = evening | 3 = night | 4+ = invalid - //TDMobList - UINT TDMobList[100]; //List of TD monsters waiting to be spawned - UINT TDNextSpawn; //index pointer for next spawn in TDMobList - UINT TDNextMon; //index pointer for next addition to TDMobList - clock_t lastTDSpawnTime; //time of the last spawn - UINT TDMobDelay; // delay between spawns (ms) - UINT crystalhealth; // current health of the base crystal - UINT portalhealth; // current health of the spawn portal - UINT mapXPRate; // exp rate for this map - - - - vector RespawnList; // RespawnZones List - vector MonsterSpawnList; // Monster spawn in this map -#ifdef USEIFO - vector MobGroupList; // Spawn "Zones" -#endif - vector MonsterList; // Monster List in this map - vector DropsList; // Droped Items - vector PlayerList; // Client list in this map; - vector NPCList; // NPC in this map - vector TeleGateList; // Telegates from this map - std::vector PointList; - - pthread_mutex_t MonsterMutex, DropMutex; -}; - -#endif diff --git a/WorldServer/WorldServer.vcxproj.user b/WorldServer/WorldServer.vcxproj.user deleted file mode 100644 index 3dd7161..0000000 --- a/WorldServer/WorldServer.vcxproj.user +++ /dev/null @@ -1,7 +0,0 @@ - - - - ..\Binary - WindowsLocalDebugger - - \ No newline at end of file