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