[svn] * Little fix in RandomMovementGenerator

* Updated to 6731 and 680

--HG--
branch : trunk
rename : 6721-676 => 6731-680
This commit is contained in:
Neo2003
2008-10-06 04:48:59 -05:00
parent 010ed993e1
commit 1fc5c0d6d7
49 changed files with 7104 additions and 6884 deletions
View File
+2
View File
@@ -2338,6 +2338,7 @@ INSERT INTO `mangos_string` VALUES
(328,'Characters at account %s (Id: %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(329,' %s (GUID %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(330,'No players found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(331,'Extended item cost %u not exist',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(400,'|cffff0000[System Message]:|rScripts reloaded',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(401,'You change security level of %s to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(402,'%s changed your security level to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
@@ -10485,6 +10486,7 @@ UNLOCK TABLES;
DROP TABLE IF EXISTS `quest_template`;
CREATE TABLE `quest_template` (
`entry` mediumint(8) unsigned NOT NULL default '0',
`Method` tinyint(3) unsigned NOT NULL default '2',
`ZoneOrSort` smallint(6) NOT NULL default '0',
`SkillOrClass` smallint(6) NOT NULL default '0',
`MinLevel` tinyint(3) unsigned NOT NULL default '0',
+4
View File
@@ -0,0 +1,4 @@
ALTER TABLE `quest_template` ADD COLUMN `Method` tinyint(3) unsigned NOT NULL default '2' AFTER `entry`;
DELETE FROM mangos_string WHERE entry IN (331);
INSERT INTO mangos_string VALUES
(331,'Extended item cost %u not exist',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -35,8 +35,8 @@ void ScriptedAI::MoveInLineOfSight(Unit *who)
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -54,8 +54,8 @@ void ScriptedAI::AttackStart(Unit* who)
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -582,8 +582,8 @@ void Scripted_NoMovementAI::MoveInLineOfSight(Unit *who)
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -601,8 +601,8 @@ void Scripted_NoMovementAI::AttackStart(Unit* who)
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -55,8 +55,6 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
case EVENT_T_SPAWNED:
ProcessEvent(*i);
break;
default:
break;
}
}
@@ -612,12 +610,18 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
caster = target;
}
//Interrupt any previous spell
if (caster->IsNonMeleeSpellCasted(false) && param3 & CAST_INTURRUPT_PREVIOUS)
caster->InterruptNonMeleeSpells(false);
//Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
bool canCast = !(caster->IsNonMeleeSpellCasted(false) && (param3 & CAST_TRIGGERED | CAST_INTURRUPT_PREVIOUS));
//Cast only if not casting or if spell is triggered
if (param3 & CAST_TRIGGERED || !caster->IsNonMeleeSpellCasted(false))
// If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
if(param3 & CAST_AURA_NOT_PRESENT)
{
for(uint8 i = 0; i < 3; ++i)
if(target->HasAura(param1, i))
return;
}
if (canCast)
{
const SpellEntry* tSpell = GetSpellStore()->LookupEntry(param1);
@@ -638,7 +642,14 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle);
}
}else caster->CastSpell(target, param1, (param3 & CAST_TRIGGERED));
}else
{
//Interrupt any previous spell
if (caster->IsNonMeleeSpellCasted(false) && param3 & CAST_INTURRUPT_PREVIOUS)
caster->InterruptNonMeleeSpells(false);
caster->CastSpell(target, param1, (param3 & CAST_TRIGGERED));
}
}else if (EAI_ErrorLevel > 0)
error_db_log("SD2: EventAI event %d creature %d attempt to cast spell that doesn't exist %d", EventId, m_creature->GetEntry(), param1);
@@ -996,11 +1007,11 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
error_db_log("SD2: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature->GetEntry(), (*i).Event.event_id, (*i).Event.event_type);
}
break;
default:
//default:
//TODO: enable below code line / verify this is correct to enable events previously disabled (ex. aggro yell), instead of enable this in void Aggro()
//(*i).Enabled = true;
//(*i).Time = 0;
break;
//break;
}
}
}
@@ -1029,8 +1040,6 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
case EVENT_T_EVADE:
ProcessEvent(*i);
break;
default:
break;
}
}
}
@@ -1050,8 +1059,6 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
case EVENT_T_DEATH:
ProcessEvent(*i, killer);
break;
default:
break;
}
}
}
@@ -1069,8 +1076,6 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
case EVENT_T_KILL:
ProcessEvent(*i, victim);
break;
default:
break;
}
}
@@ -1089,8 +1094,6 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
case EVENT_T_SUMMONED_UNIT:
ProcessEvent(*i, pUnit);
break;
default:
break;
}
}
}
@@ -1145,8 +1148,8 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -1193,8 +1196,8 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -1215,8 +1218,6 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
ProcessEvent(*i, pUnit);
}
break;
default:
break;
}
}
}
@@ -113,6 +113,7 @@ enum CastFlags
CAST_FORCE_CAST = 0x04, //Forces cast even if creature is out of mana or out of range
CAST_NO_MELEE_IF_OOM = 0x08, //Prevents creature from entering melee if out of mana or out of range
CAST_FORCE_TARGET_SELF = 0x10, //Forces the target to cast this spell on itself
CAST_AURA_NOT_PRESENT = 0x20, //Only casts the spell if the target does not have an aura from the spell
};
enum EventFlags
@@ -104,8 +104,6 @@ struct MANGOS_DLL_DECL mob_stolen_soulAI : public ScriptedAI
DoCast(m_creature->getVictim(), SPELL_MOONFIRE);
Class_Timer = 10000;
break;
default:
break;
}
}else Class_Timer -= diff;
@@ -204,8 +202,8 @@ struct MANGOS_DLL_DECL boss_exarch_maladaarAI : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -106,8 +106,8 @@ struct MANGOS_DLL_DECL boss_nexusprince_shaffarAI : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -115,8 +115,8 @@ struct MANGOS_DLL_DECL boss_talon_king_ikissAI : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -125,8 +125,8 @@ struct MANGOS_DLL_DECL boss_grandmaster_vorpilAI : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -74,8 +74,8 @@ struct MANGOS_DLL_DECL boss_murmurAI : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -95,8 +95,8 @@ struct MANGOS_DLL_DECL boss_murmurAI : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -61,8 +61,8 @@ struct MANGOS_DLL_DECL npc_ragged_johnAI : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -117,8 +117,8 @@ struct MANGOS_DLL_DECL boss_omor_the_unscarredAI : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -138,8 +138,8 @@ struct MANGOS_DLL_DECL boss_omor_the_unscarredAI : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -108,8 +108,8 @@ struct MANGOS_DLL_DECL boss_watchkeeper_gargolmarAI : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
else if (!HasTaunted && m_creature->IsWithinDistInMap(who, 60.0f))
@@ -200,8 +200,8 @@ struct MANGOS_DLL_DECL boss_grand_warlock_nethekurseAI : public ScriptedAI
if( !InCombat )
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -237,8 +237,8 @@ struct MANGOS_DLL_DECL boss_grand_warlock_nethekurseAI : public ScriptedAI
if( !InCombat )
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -582,13 +582,13 @@ struct MANGOS_DLL_DECL boss_malchezaarAI : public ScriptedAI
if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE) && !m_creature->IsNonMeleeSpellCasted(false))
{
//Check for base attack
if( m_creature->isAttackReady())
if( m_creature->isAttackReady() && m_creature->getVictim() )
{
m_creature->AttackerStateUpdate(m_creature->getVictim());
m_creature->resetAttackTimer();
}
//Check for offhand attack
if( m_creature->isAttackReady(OFF_ATTACK))
if( m_creature->isAttackReady(OFF_ATTACK) && m_creature->getVictim() )
{
m_creature->AttackerStateUpdate(m_creature->getVictim(), OFF_ATTACK);
m_creature->resetAttackTimer(OFF_ATTACK);
@@ -163,9 +163,6 @@ class MANGOS_DLL_SPEC instance_molten_core : public ScriptedInstance
case ID_FLAMEWAKERPRIEST:
FlamewakerPriest = creature->GetGUID();
break;
default:
return;
}
}
@@ -264,8 +264,6 @@ struct MANGOS_DLL_DECL npc_manaforge_control_consoleAI : public ScriptedAI
}
++Phase;
break;
default:
break;
}
} else Event_Timer -= diff;
@@ -138,8 +138,8 @@ struct MANGOS_DLL_DECL npc_millhouse_manastormAI : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -153,8 +153,8 @@ struct MANGOS_DLL_DECL npc_millhouse_manastormAI : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -444,8 +444,6 @@ struct MANGOS_DLL_DECL npc_warden_mellicharAI : public ScriptedAI
case 7:
pInstance->SetData(TYPE_WARDEN_5,IN_PROGRESS);
break;
default:
break;
}
CanSpawn = true;
}
@@ -505,8 +503,6 @@ struct MANGOS_DLL_DECL npc_warden_mellicharAI : public ScriptedAI
DoYell(YELL_WELCOME,LANG_UNIVERSAL,NULL);
DoPlaySoundToSet(m_creature,SOUND_WELCOME);
break;
default:
break;
}
CanSpawn = false;
++Phase;
@@ -553,8 +549,6 @@ struct MANGOS_DLL_DECL npc_warden_mellicharAI : public ScriptedAI
DoPrepareForPhase();
EventProgress_Timer = 15000;
break;
default:
break;
}
}
} else EventProgress_Timer -= diff;
@@ -130,8 +130,8 @@ struct MANGOS_DLL_DECL boss_harbinger_skyrissAI : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -148,8 +148,8 @@ struct MANGOS_DLL_DECL boss_harbinger_skyrissAI : public ScriptedAI
if( !InCombat )
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -236,8 +236,6 @@ struct MANGOS_DLL_DECL boss_harbinger_skyrissAI : public ScriptedAI
case 3:
Intro = true;
break;
default:
break;
}
}else Intro_Timer -=diff;
}
@@ -215,8 +215,8 @@ struct MANGOS_DLL_DECL advisorbase_ai : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -234,8 +234,8 @@ struct MANGOS_DLL_DECL advisorbase_ai : public ScriptedAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -863,14 +863,10 @@ struct MANGOS_DLL_DECL boss_kaelthasAI : public ScriptedAI
DoYell(SAY_SUMMON_PHOENIX1, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_SUMMON_PHOENIX1);
break;
case 1:
DoYell(SAY_SUMMON_PHOENIX2, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_SUMMON_PHOENIX2);
break;
default:
break;
}
Phoenix_Timer = 60000;
@@ -1252,8 +1248,8 @@ struct MANGOS_DLL_DECL boss_grand_astromancer_capernianAI : public advisorbase_a
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
@@ -665,8 +665,8 @@ struct MANGOS_DLL_DECL boss_veklorAI : public boss_twinemperorsAI
if (!InCombat)
{
Aggro(who);
InCombat = true;
Aggro(who);
}
}
}
-56
View File
@@ -34,62 +34,6 @@
bool ChatHandler::load_command_table = true;
LanguageDesc lang_description[LANGUAGES_COUNT] =
{
{ LANG_ADDON, 0, 0 },
{ LANG_UNIVERSAL, 0, 0 },
{ LANG_ORCISH, 669, SKILL_LANG_ORCISH },
{ LANG_DARNASSIAN, 671, SKILL_LANG_DARNASSIAN },
{ LANG_TAURAHE, 670, SKILL_LANG_TAURAHE },
{ LANG_DWARVISH, 672, SKILL_LANG_DWARVEN },
{ LANG_COMMON, 668, SKILL_LANG_COMMON },
{ LANG_DEMONIC, 815, SKILL_LANG_DEMON_TONGUE },
{ LANG_TITAN, 816, SKILL_LANG_TITAN },
{ LANG_THALASSIAN, 813, SKILL_LANG_THALASSIAN },
{ LANG_DRACONIC, 814, SKILL_LANG_DRACONIC },
{ LANG_KALIMAG, 817, SKILL_LANG_OLD_TONGUE },
{ LANG_GNOMISH, 7340, SKILL_LANG_GNOMISH },
{ LANG_TROLL, 7341, SKILL_LANG_TROLL },
{ LANG_GUTTERSPEAK, 17737, SKILL_LANG_GUTTERSPEAK },
{ LANG_DRAENEI, 29932, SKILL_LANG_DRAENEI },
{ LANG_ZOMBIE, 0, 0 },
{ LANG_GNOMISH_BINARY, 0, 0 },
{ LANG_GOBLIN_BINARY, 0, 0 }
};
LanguageDesc const* GetLanguageDescByID(uint32 lang)
{
for(int i = 0; i < LANGUAGES_COUNT; ++i)
{
if(uint32(lang_description[i].lang_id) == lang)
return &lang_description[i];
}
return NULL;
}
LanguageDesc const* GetLanguageDescBySpell(uint32 spell_id)
{
for(int i = 0; i < LANGUAGES_COUNT; ++i)
{
if(lang_description[i].spell_id == spell_id)
return &lang_description[i];
}
return NULL;
}
LanguageDesc const* GetLanguageDescBySkill(uint32 skill_id)
{
for(int i = 0; i < LANGUAGES_COUNT; ++i)
{
if(lang_description[i].skill_id == skill_id)
return &lang_description[i];
}
return NULL;
}
ChatCommand * ChatHandler::getCommandTable()
{
static ChatCommand serverCommandTable[] =
-13
View File
@@ -28,19 +28,6 @@ class Player;
class Unit;
struct GameTele;
struct LanguageDesc
{
Language lang_id;
uint32 spell_id;
uint32 skill_id;
};
extern LanguageDesc lang_description[LANGUAGES_COUNT];
LanguageDesc const* GetLanguageDescByID(uint32 lang);
LanguageDesc const* GetLanguageDescBySpell(uint32 spell_id);
LanguageDesc const* GetLanguageDescBySkill(uint32 skill_id);
class ChatCommand
{
public:
+127 -34
View File
@@ -62,15 +62,36 @@ TrainerSpell const* TrainerSpellData::Find(uint32 spell_id) const
return NULL;
}
bool VendorItemData::RemoveItem( uint32 item_id )
{
for(VendorItemList::iterator i = m_items.begin(); i != m_items.end(); ++i )
{
if((*i)->item==item_id)
{
m_items.erase(i);
return true;
}
}
return false;
}
VendorItem const* VendorItemData::FindItem(uint32 item_id) const
{
for(VendorItemList::const_iterator i = m_items.begin(); i != m_items.end(); ++i )
if((*i)->item==item_id)
return *i;
return NULL;
}
Creature::Creature() :
Unit(), i_AI(NULL),
lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0),
m_itemsLoaded(false), m_lootMoney(0), m_lootRecipient(0),
m_lootMoney(0), m_lootRecipient(0),
m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f),
m_gossipOptionLoaded(false),m_emoteState(0), m_isPet(false), m_isTotem(false),
m_regenTimer(2000), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0),
m_AlreadyCallAssistence(false), m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false),
m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),m_creatureInfo(NULL)
m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),m_creatureInfo(NULL), m_DBTableGuid(0)
{
m_valuesCount = UNIT_END;
@@ -87,7 +108,7 @@ Creature::~Creature()
{
CleanupsBeforeDelete();
m_vendor_items.clear();
m_vendorItemCounts.clear();
delete i_AI;
i_AI = NULL;
@@ -503,6 +524,7 @@ bool Creature::Create (uint32 guidlow, Map *map, uint32 Entry, uint32 team, cons
m_corpseDelay = sWorld.getConfig(CONFIG_CORPSE_DECAY_NORMAL);
break;
}
LoadCreaturesAddon();
}
return bResult;
@@ -673,16 +695,16 @@ void Creature::prepareGossipMenu( Player *pPlayer,uint32 gossipid )
cantalking=false;
break;
case GOSSIP_OPTION_VENDOR:
// load vendor items if not yet
LoadGoods();
if(!GetItemCount())
{
VendorItemData const* vItems = GetVendorItems();
if(!vItems || vItems->Empty())
{
sLog.outErrorDb("Creature %u (Entry: %u) have UNIT_NPC_FLAG_VENDOR but have empty trading item list.",
GetGUIDLow(),GetEntry());
cantalking=false;
}
break;
}
case GOSSIP_OPTION_TRAINER:
if(!isCanTrainingOf(pPlayer,false))
cantalking=false;
@@ -934,6 +956,9 @@ uint32 Creature::GetGossipTextId(uint32 action, uint32 zoneid)
uint32 Creature::GetNpcTextId()
{
if (!m_DBTableGuid)
return DEFAULT_GOSSIP_MESSAGE;
if(uint32 pos = objmgr.GetNpcGossip(m_DBTableGuid))
return pos;
@@ -1046,6 +1071,8 @@ void Creature::SaveToDB()
void Creature::SaveToDB(uint32 mapid, uint8 spawnMask)
{
// update in loaded data
if (!m_DBTableGuid)
m_DBTableGuid = GetGUIDLow();
CreatureData& data = objmgr.NewOrExistCreatureData(m_DBTableGuid);
uint32 displayId = GetNativeDisplayId();
@@ -1237,7 +1264,6 @@ bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, uint32 team, const
Object::_Create(guidlow, Entry, HIGHGUID_UNIT);
m_DBTableGuid = guidlow;
if(!UpdateEntry(Entry, team, data))
return false;
@@ -1263,7 +1289,7 @@ bool Creature::LoadFromDB(uint32 guid, Map *map)
return false;
}
uint32 stored_guid = guid;
m_DBTableGuid = guid;
if (map->GetInstanceId() != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_UNIT);
uint16 team = 0;
@@ -1278,9 +1304,6 @@ bool Creature::LoadFromDB(uint32 guid, Map *map)
return false;
}
m_DBTableGuid = stored_guid;
LoadCreaturesAddon();
m_respawnradius = data->spawndist;
m_respawnDelay = data->spawntimesecs;
@@ -1346,24 +1369,6 @@ void Creature::LoadEquipment(uint32 equip_entry, bool force)
}
}
void Creature::LoadGoods()
{
// already loaded;
if(m_itemsLoaded)
return;
m_vendor_items.clear();
VendorItemList const* vList = objmgr.GetNpcVendorItemList(GetEntry());
if(!vList)
return;
for (VendorItemList::const_iterator _item_iter = vList->begin(); _item_iter != vList->end(); ++_item_iter)
AddItem( (*_item_iter)->item, (*_item_iter)->maxcount, (*_item_iter)->incrtime, (*_item_iter)->ExtendedCost);
m_itemsLoaded = true;
}
bool Creature::hasQuest(uint32 quest_id) const
{
QuestRelations const& qr = objmgr.mCreatureQuestRelations;
@@ -1388,6 +1393,12 @@ bool Creature::hasInvolvedQuest(uint32 quest_id) const
void Creature::DeleteFromDB()
{
if (!m_DBTableGuid)
{
sLog.outDebug("Trying to delete not saved creature!");
return;
}
objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),0);
objmgr.DeleteCreatureData(m_DBTableGuid);
@@ -1494,7 +1505,8 @@ void Creature::Respawn()
if(getDeathState()==DEAD)
{
objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),0);
if (m_DBTableGuid)
objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),0);
m_respawnTime = time(NULL); // respawn at next tick
}
}
@@ -1716,7 +1728,7 @@ void Creature::CallAssistence()
void Creature::SaveRespawnTime()
{
if(isPet())
if(isPet() || !m_DBTableGuid)
return;
if(m_respawnTime > time(NULL)) // dead (no corpse)
@@ -1752,8 +1764,11 @@ bool Creature::IsOutOfThreatArea(Unit* pVictim) const
CreatureDataAddon const* Creature::GetCreatureAddon() const
{
if(CreatureDataAddon const* addon = ObjectMgr::GetCreatureAddon(m_DBTableGuid))
return addon;
if (m_DBTableGuid)
{
if(CreatureDataAddon const* addon = ObjectMgr::GetCreatureAddon(m_DBTableGuid))
return addon;
}
// dependent from heroic mode entry
return ObjectMgr::GetCreatureTemplateAddon(GetCreatureInfo()->Entry);
@@ -1956,6 +1971,84 @@ char const* Creature::GetScriptName() const
return ObjectMgr::GetCreatureTemplate(GetEntry())->ScriptName;
}
VendorItemData const* Creature::GetVendorItems() const
{
return objmgr.GetNpcVendorItemList(GetEntry());
}
uint32 Creature::GetVendorItemCurrentCount(VendorItem const* vItem)
{
if(!vItem->maxcount)
return vItem->maxcount;
VendorItemCounts::iterator itr = m_vendorItemCounts.begin();
for(; itr != m_vendorItemCounts.end(); ++itr)
if(itr->itemId==vItem->item)
break;
if(itr == m_vendorItemCounts.end())
return vItem->maxcount;
VendorItemCount* vCount = &*itr;
time_t ptime = time(NULL);
if( vCount->lastIncrementTime + vItem->incrtime <= ptime )
{
ItemPrototype const* pProto = objmgr.GetItemPrototype(vItem->item);
uint32 diff = uint32((ptime - vCount->lastIncrementTime)/vItem->incrtime);
if((vCount->count + diff * pProto->BuyCount) >= vItem->maxcount )
{
m_vendorItemCounts.erase(itr);
return vItem->maxcount;
}
vCount->count += diff * pProto->BuyCount;
vCount->lastIncrementTime = ptime;
}
return vCount->count;
}
uint32 Creature::UpdateVendorItemCurrentCount(VendorItem const* vItem, uint32 used_count)
{
if(!vItem->maxcount)
return 0;
VendorItemCounts::iterator itr = m_vendorItemCounts.begin();
for(; itr != m_vendorItemCounts.end(); ++itr)
if(itr->itemId==vItem->item)
break;
if(itr == m_vendorItemCounts.end())
{
uint32 new_count = vItem->maxcount > used_count ? vItem->maxcount-used_count : 0;
m_vendorItemCounts.push_back(VendorItemCount(vItem->item,new_count));
return new_count;
}
VendorItemCount* vCount = &*itr;
time_t ptime = time(NULL);
if( vCount->lastIncrementTime + vItem->incrtime <= ptime )
{
ItemPrototype const* pProto = objmgr.GetItemPrototype(vItem->item);
uint32 diff = uint32((ptime - vCount->lastIncrementTime)/vItem->incrtime);
if((vCount->count + diff * pProto->BuyCount) < vItem->maxcount )
vCount->count += diff * pProto->BuyCount;
else
vCount->count = vItem->maxcount;
}
vCount->count = vCount->count > used_count ? vCount->count-used_count : 0;
vCount->lastIncrementTime = ptime;
return vCount->count;
}
TrainerSpellData const* Creature::GetTrainerSpells() const
{
return objmgr.GetNpcTrainerSpells(GetEntry());
+55 -52
View File
@@ -112,19 +112,6 @@ struct GossipOption
std::string Option;
};
struct CreatureItem
{
CreatureItem(uint32 _item, uint32 _maxcount, uint32 _incrtime, uint32 _ExtendedCost)
: id(_item), count(_maxcount), maxcount(_maxcount), incrtime(_incrtime), ExtendedCost(_ExtendedCost), lastincr((uint32)time(NULL)) {}
uint32 id;
uint32 count;
uint32 maxcount;
uint32 incrtime;
uint32 lastincr;
uint32 ExtendedCost;
};
enum CreatureFlagsExtra
{
CREATURE_FLAG_EXTRA_INSTANCE_BIND = 0x00000001, // creature kill bind instance with killer and killer's group
@@ -291,6 +278,56 @@ enum InhabitTypeValues
#pragma pack(pop)
#endif
// Vendors
struct VendorItem
{
VendorItem(uint32 _item, uint32 _maxcount, uint32 _incrtime, uint32 _ExtendedCost)
: item(_item), maxcount(_maxcount), incrtime(_incrtime), ExtendedCost(_ExtendedCost) {}
uint32 item;
uint32 maxcount; // 0 for infinity item amount
uint32 incrtime; // time for restore items amount if maxcount != 0
uint32 ExtendedCost;
};
typedef std::vector<VendorItem*> VendorItemList;
struct VendorItemData
{
VendorItemList m_items;
VendorItem* GetItem(uint32 slot) const
{
if(slot>=m_items.size()) return NULL;
return m_items[slot];
}
bool Empty() const { return m_items.empty(); }
uint8 GetItemCount() const { return m_items.size(); }
void AddItem( uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost)
{
m_items.push_back(new VendorItem(item, maxcount, ptime, ExtendedCost));
}
bool RemoveItem( uint32 item_id );
VendorItem const* FindItem(uint32 item_id) const;
void Clear()
{
for (VendorItemList::iterator itr = m_items.begin(); itr != m_items.end(); ++itr)
delete (*itr);
}
};
struct VendorItemCount
{
explicit VendorItemCount(uint32 _item, uint32 _count)
: itemId(_item), count(_count), lastIncrementTime(time(NULL)) {}
uint32 itemId;
uint32 count;
time_t lastIncrementTime;
};
typedef std::list<VendorItemCount> VendorItemCounts;
struct TrainerSpell
{
uint32 spell;
@@ -418,41 +455,9 @@ class MANGOS_DLL_SPEC Creature : public Unit
uint32 GetCurrentEquipmentId() { return m_equipmentId; }
float GetSpellDamageMod(int32 Rank);
/*********************************************************/
/*** VENDOR SYSTEM ***/
/*********************************************************/
void LoadGoods(); // must be called before access to vendor items, lazy loading at first call
void ReloadGoods() { m_itemsLoaded = false; LoadGoods(); }
CreatureItem* GetItem(uint32 slot)
{
if(slot>=m_vendor_items.size()) return NULL;
return &m_vendor_items[slot];
}
uint8 GetItemCount() const { return m_vendor_items.size(); }
void AddItem( uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost)
{
m_vendor_items.push_back(CreatureItem(item, maxcount, ptime, ExtendedCost));
}
bool RemoveItem( uint32 item_id )
{
for(CreatureItems::iterator i = m_vendor_items.begin(); i != m_vendor_items.end(); ++i )
{
if(i->id==item_id)
{
m_vendor_items.erase(i);
return true;
}
}
return false;
}
CreatureItem* FindItem(uint32 item_id)
{
for(CreatureItems::iterator i = m_vendor_items.begin(); i != m_vendor_items.end(); ++i )
if(i->id==item_id)
return &*i;
return NULL;
}
VendorItemData const* GetVendorItems() const;
uint32 GetVendorItemCurrentCount(VendorItem const* vItem);
uint32 UpdateVendorItemCurrentCount(VendorItem const* vItem, uint32 used_count);
TrainerSpellData const* GetTrainerSpells() const;
@@ -562,9 +567,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL);
// vendor items
typedef std::vector<CreatureItem> CreatureItems;
CreatureItems m_vendor_items;
bool m_itemsLoaded; // vendor items loading state
VendorItemCounts m_vendorItemCounts;
void _RealtimeSetCreatureInfo();
@@ -592,7 +595,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
uint32 m_regenTimer;
MovementGeneratorType m_defaultMovementType;
Cell m_currentCell; // store current cell where creature listed
uint32 m_DBTableGuid;
uint32 m_DBTableGuid; ///< For new or temporary creatures is 0 for saved it is lowguid
uint32 m_equipmentId;
bool m_AlreadyCallAssistence;
+1247 -1253
View File
File diff suppressed because it is too large Load Diff
+592 -592
View File
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -391,7 +391,7 @@ void PlayerMenu::SendQuestGiverStatus( uint8 questStatus, uint64 npcGUID )
data << uint8(questStatus);
pSession->SendPacket( &data );
//sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_STATUS NPC Guid=%u, status=%u",GUID_LOPART(npcGUID),questStatus);
sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_STATUS NPC Guid=%u, status=%u",GUID_LOPART(npcGUID),questStatus);
}
void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID, bool ActivateAccept )
@@ -477,7 +477,7 @@ void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID
}
pSession->SendPacket( &data );
//sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_DETAILS NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId());
sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_DETAILS NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId());
}
void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest )
@@ -515,7 +515,7 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest )
WorldPacket data( SMSG_QUEST_QUERY_RESPONSE, 100 ); // guess size
data << uint32(pQuest->GetQuestId());
data << uint32(pQuest->GetMinLevel()); // not MinLevel. Accepted values: 0, 1 or 2 Possible theory for future dev: 0==cannot in quest log, 1==can in quest log session only(removed on log out), 2==can in quest log always (save to db)
data << uint32(pQuest->GetQuestMethod()); // Accepted values: 0, 1 or 2. 0==IsAutoComplete() (skip objectives/details)
data << uint32(pQuest->GetQuestLevel()); // may be 0
data << uint32(pQuest->GetZoneOrSort()); // zone or sort to display in quest log
@@ -597,7 +597,7 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest )
data << ObjectiveText[iI];
pSession->SendPacket( &data );
//sLog.outDebug( "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u",pQuest->GetQuestId() );
sLog.outDebug( "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u",pQuest->GetQuestId() );
}
void PlayerMenu::SendQuestGiverOfferReward( Quest const* pQuest, uint64 npcGUID, bool EnbleNext )
@@ -679,7 +679,7 @@ void PlayerMenu::SendQuestGiverOfferReward( Quest const* pQuest, uint64 npcGUID,
data << uint32(pQuest->GetRewSpellCast()); // casted spell
data << uint32(0); // Honor points reward, not implemented
pSession->SendPacket( &data );
//sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() );
sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() );
}
void PlayerMenu::SendQuestGiverRequestItems( Quest const *pQuest, uint64 npcGUID, bool Completable, bool CloseOnCancel )
@@ -758,5 +758,5 @@ void PlayerMenu::SendQuestGiverRequestItems( Quest const *pQuest, uint64 npcGUID
data << uint32(0x04) << uint32(0x08) << uint32(0x10);
pSession->SendPacket( &data );
//sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() );
sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() );
}
+1211 -1221
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -303,6 +303,7 @@ enum MangosStrings
LANG_LOOKUP_PLAYER_ACCOUNT = 328,
LANG_LOOKUP_PLAYER_CHARACTER = 329,
LANG_NO_PLAYERS_FOUND = 330,
LANG_EXTENDED_COST_NOT_EXIST = 331,
// Room for more level 2
+11 -48
View File
@@ -1237,14 +1237,6 @@ bool ChatHandler::HandleAddVendorItemCommand(const char* args)
if (!*args)
return false;
Creature* vendor = getSelectedCreature();
if (!vendor || !vendor->isVendor())
{
SendSysMessage(LANG_COMMAND_VENDORSELECTION);
SetSentErrorMessage(true);
return false;
}
char* pitem = extractKeyFromLink((char*)args,"Hitem");
if (!pitem)
{
@@ -1252,6 +1244,7 @@ bool ChatHandler::HandleAddVendorItemCommand(const char* args)
SetSentErrorMessage(true);
return false;
}
uint32 itemId = atol(pitem);
char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0
@@ -1267,41 +1260,20 @@ bool ChatHandler::HandleAddVendorItemCommand(const char* args)
char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0
uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0;
ItemPrototype const *pProto = objmgr.GetItemPrototype(itemId);
if(!pProto)
Creature* vendor = getSelectedCreature();
uint32 vendor_entry = vendor ? vendor->GetEntry() : 0;
if(!objmgr.IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,m_session->GetPlayer()))
{
PSendSysMessage(LANG_ITEM_NOT_FOUND, itemId);
SetSentErrorMessage(true);
return false;
}
if(extendedcost && !sItemExtendedCostStore.LookupEntry(extendedcost))
{
PSendSysMessage(LANG_BAD_VALUE, extendedcost);
SetSentErrorMessage(true);
return false;
}
objmgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost);
// load vendor items if not yet
vendor->LoadGoods();
ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
if(vendor->FindItem(itemId))
{
PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST,itemId);
SetSentErrorMessage(true);
return false;
}
if (vendor->GetItemCount() >= MAX_VENDOR_ITEMS)
{
SendSysMessage(LANG_COMMAND_ADDVENDORITEMITEMS);
SetSentErrorMessage(true);
return false;
}
// add to DB and to current ingame vendor
WorldDatabase.PExecuteLog("INSERT INTO npc_vendor (entry,item,maxcount,incrtime,extendedcost) VALUES('%u','%u','%u','%u','%u')",vendor->GetEntry(), itemId, maxcount,incrtime,extendedcost);
vendor->AddItem(itemId,maxcount,incrtime,extendedcost);
PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost);
return true;
}
@@ -1329,25 +1301,16 @@ bool ChatHandler::HandleDelVendorItemCommand(const char* args)
}
uint32 itemId = atol(pitem);
ItemPrototype const *pProto = objmgr.GetItemPrototype(itemId);
if(!pProto)
{
PSendSysMessage(LANG_ITEM_NOT_FOUND, itemId);
SetSentErrorMessage(true);
return false;
}
// load vendor items if not yet
vendor->LoadGoods();
if (!vendor->RemoveItem(itemId))
if(!objmgr.RemoveVendorItem(vendor->GetEntry(),itemId))
{
PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId);
SetSentErrorMessage(true);
return false;
}
WorldDatabase.PExecuteLog("DELETE FROM npc_vendor WHERE entry='%u' AND item='%u'",vendor->GetEntry(), itemId);
ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1);
return true;
}
+185 -64
View File
@@ -70,6 +70,40 @@ bool normalizePlayerName(std::string& name)
return true;
}
LanguageDesc lang_description[LANGUAGES_COUNT] =
{
{ LANG_ADDON, 0, 0 },
{ LANG_UNIVERSAL, 0, 0 },
{ LANG_ORCISH, 669, SKILL_LANG_ORCISH },
{ LANG_DARNASSIAN, 671, SKILL_LANG_DARNASSIAN },
{ LANG_TAURAHE, 670, SKILL_LANG_TAURAHE },
{ LANG_DWARVISH, 672, SKILL_LANG_DWARVEN },
{ LANG_COMMON, 668, SKILL_LANG_COMMON },
{ LANG_DEMONIC, 815, SKILL_LANG_DEMON_TONGUE },
{ LANG_TITAN, 816, SKILL_LANG_TITAN },
{ LANG_THALASSIAN, 813, SKILL_LANG_THALASSIAN },
{ LANG_DRACONIC, 814, SKILL_LANG_DRACONIC },
{ LANG_KALIMAG, 817, SKILL_LANG_OLD_TONGUE },
{ LANG_GNOMISH, 7340, SKILL_LANG_GNOMISH },
{ LANG_TROLL, 7341, SKILL_LANG_TROLL },
{ LANG_GUTTERSPEAK, 17737, SKILL_LANG_GUTTERSPEAK },
{ LANG_DRAENEI, 29932, SKILL_LANG_DRAENEI },
{ LANG_ZOMBIE, 0, 0 },
{ LANG_GNOMISH_BINARY, 0, 0 },
{ LANG_GOBLIN_BINARY, 0, 0 }
};
LanguageDesc const* GetLanguageDescByID(uint32 lang)
{
for(int i = 0; i < LANGUAGES_COUNT; ++i)
{
if(uint32(lang_description[i].lang_id) == lang)
return &lang_description[i];
}
return NULL;
}
ObjectMgr::ObjectMgr()
{
m_hiCharGuid = 1;
@@ -134,8 +168,7 @@ ObjectMgr::~ObjectMgr()
delete itr->second;
for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr)
for (VendorItemList::iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2)
delete (*itr2);
itr->second.Clear();
for (CacheTrainerSpellMap::iterator itr = m_mCacheTrainerSpellMap.begin(); itr != m_mCacheTrainerSpellMap.end(); ++itr)
itr->second.Clear();
@@ -2697,35 +2730,35 @@ void ObjectMgr::LoadQuests()
mExclusiveQuestGroups.clear();
// 0 1 2 3 4 5 6 7
QueryResult *result = WorldDatabase.Query("SELECT entry, ZoneOrSort, SkillOrClass, MinLevel, QuestLevel, Type, RequiredRaces, RequiredSkillValue,"
// 8 9 10 11 12 13 14 15
// 0 1 2 3 4 5 6 7 8
QueryResult *result = WorldDatabase.Query("SELECT entry, Method, ZoneOrSort, SkillOrClass, MinLevel, QuestLevel, Type, RequiredRaces, RequiredSkillValue,"
// 9 10 11 12 13 14 15 16
"RepObjectiveFaction, RepObjectiveValue, RequiredMinRepFaction, RequiredMinRepValue, RequiredMaxRepFaction, RequiredMaxRepValue, SuggestedPlayers, LimitTime,"
// 16 17 18 19 20 21 22 23 24 25
// 17 18 19 20 21 22 23 24 25 26
"QuestFlags, SpecialFlags, CharTitleId, PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestInChain, SrcItemId, SrcItemCount, SrcSpell,"
// 26 27 28 29 30 31 32 33 34 35
// 27 28 29 30 31 32 33 34 35 36
"Title, Details, Objectives, OfferRewardText, RequestItemsText, EndText, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4,"
// 36 37 38 39 40 41 42 43
// 37 38 39 40 41 42 43 44
"ReqItemId1, ReqItemId2, ReqItemId3, ReqItemId4, ReqItemCount1, ReqItemCount2, ReqItemCount3, ReqItemCount4,"
// 44 45 46 47 48 49 50 51 52 53 54 55
// 45 46 47 48 49 50 51 52 53 54 54 55
"ReqSourceId1, ReqSourceId2, ReqSourceId3, ReqSourceId4, ReqSourceCount1, ReqSourceCount2, ReqSourceCount3, ReqSourceCount4, ReqSourceRef1, ReqSourceRef2, ReqSourceRef3, ReqSourceRef4,"
// 56 57 58 59 60 61 62 63
// 57 58 59 60 61 62 63 64
"ReqCreatureOrGOId1, ReqCreatureOrGOId2, ReqCreatureOrGOId3, ReqCreatureOrGOId4, ReqCreatureOrGOCount1, ReqCreatureOrGOCount2, ReqCreatureOrGOCount3, ReqCreatureOrGOCount4,"
// 64 65 66 67
// 65 66 67 68
"ReqSpellCast1, ReqSpellCast2, ReqSpellCast3, ReqSpellCast4,"
// 68 69 70 71 72 73
// 69 70 71 72 73 74
"RewChoiceItemId1, RewChoiceItemId2, RewChoiceItemId3, RewChoiceItemId4, RewChoiceItemId5, RewChoiceItemId6,"
// 74 75 76 77 78 79
// 75 76 77 78 79 80
"RewChoiceItemCount1, RewChoiceItemCount2, RewChoiceItemCount3, RewChoiceItemCount4, RewChoiceItemCount5, RewChoiceItemCount6,"
// 80 81 82 83 84 85 86 87
// 81 82 83 84 85 86 87 88
"RewItemId1, RewItemId2, RewItemId3, RewItemId4, RewItemCount1, RewItemCount2, RewItemCount3, RewItemCount4,"
// 88 89 90 91 92 93 94 95 96 97
// 89 90 91 92 93 94 95 96 97 98
"RewRepFaction1, RewRepFaction2, RewRepFaction3, RewRepFaction4, RewRepFaction5, RewRepValue1, RewRepValue2, RewRepValue3, RewRepValue4, RewRepValue5,"
// 98 99 100 101 102 103 104 105 106 107
// 99 100 101 102 103 104 105 106 107 108
"RewOrReqMoney, RewMoneyMaxLevel, RewSpell, RewSpellCast, RewMailTemplateId, RewMailDelaySecs, PointMapId, PointX, PointY, PointOpt,"
// 108 109 110 111 112 113 114 115 116 117
// 109 110 111 112 113 114 115 116 117 118
"DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4,IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4,"
// 118 119
// 119 120
"StartScript, CompleteScript"
" FROM quest_template");
if(result == NULL)
@@ -2761,6 +2794,11 @@ void ObjectMgr::LoadQuests()
// additional quest integrity checks (GO, creature_template and item_template must be loaded already)
if( qinfo->GetQuestMethod() >= 3 )
{
sLog.outErrorDb("Quest %u has `Method` = %u, expected values are 0, 1 or 2.",qinfo->GetQuestId(),qinfo->GetQuestMethod());
}
if (qinfo->QuestFlags & ~QUEST_MANGOS_FLAGS_DB_ALLOWED)
{
sLog.outErrorDb("Quest %u has `SpecialFlags` = %u > max allowed value. Correct `SpecialFlags` to value <= %u",
@@ -6148,14 +6186,14 @@ bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min
if(entry==0)
{
sLog.outString("Table `%s` contain reserved entry 0, ignored.",table);
sLog.outErrorDb("Table `%s` contain reserved entry 0, ignored.",table);
continue;
}
else if(entry < min_value || entry > max_value)
{
int32 start = min_value > 0 ? min_value : max_value;
int32 end = min_value > 0 ? max_value : min_value;
sLog.outString("Table `%s` contain entry %i out of allowed range (%d - %d), ignored.",table,entry,start,end);
sLog.outErrorDb("Table `%s` contain entry %i out of allowed range (%d - %d), ignored.",table,entry,start,end);
continue;
}
@@ -6163,7 +6201,7 @@ bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min
if(data.Content.size() > 0)
{
sLog.outString("Table `%s` contain data for already loaded entry %i (from another table?), ignored.",table,entry);
sLog.outErrorDb("Table `%s` contain data for already loaded entry %i (from another table?), ignored.",table,entry);
continue;
}
@@ -6656,22 +6694,30 @@ void ObjectMgr::LoadTrainerSpell()
barGoLink bar( result->GetRowCount() );
uint32 count = 0,entry,spell;
uint32 count = 0;
do
{
bar.step();
Field* fields = result->Fetch();
entry = fields[0].GetUInt32();
spell = fields[1].GetUInt32();
uint32 entry = fields[0].GetUInt32();
uint32 spell = fields[1].GetUInt32();
if(!GetCreatureTemplate(entry))
CreatureInfo const* cInfo = GetCreatureTemplate(entry);
if(!cInfo)
{
sLog.outErrorDb("Table `npc_trainer` have entry for not existed creature template (Entry: %u), ignore", entry);
continue;
}
if(!(cInfo->npcflag & UNIT_NPC_FLAG_TRAINER))
{
sLog.outErrorDb("Table `npc_trainer` have data for not creature template (Entry: %u) without trainer flag, ignore", entry);
continue;
}
SpellEntry const *spellinfo = sSpellStore.LookupEntry(spell);
if(!spellinfo)
{
@@ -6715,10 +6761,7 @@ void ObjectMgr::LoadVendors()
{
// For reload case
for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr)
{
for (VendorItemList::iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2)
delete (*itr2);
}
itr->second.Clear();
m_mCacheVendorItemMap.clear();
QueryResult *result = WorldDatabase.PQuery("SELECT entry, item, maxcount, incrtime, ExtendedCost FROM npc_vendor");
@@ -6736,48 +6779,23 @@ void ObjectMgr::LoadVendors()
barGoLink bar( result->GetRowCount() );
uint32 count = 0;
uint32 entry, item_id, ExtendedCost;
do
{
bar.step();
Field* fields = result->Fetch();
entry = fields[0].GetUInt32();
if(!GetCreatureTemplate(entry))
{
sLog.outErrorDb("Table `npc_vendor` have data for not existed creature template (Entry: %u), ignore", entry);
uint32 entry = fields[0].GetUInt32();
uint32 item_id = fields[1].GetUInt32();
uint32 maxcount = fields[2].GetUInt32();
uint32 incrtime = fields[3].GetUInt32();
uint32 ExtendedCost = fields[4].GetUInt32();
if(!IsVendorItemValid(entry,item_id,maxcount,incrtime,ExtendedCost))
continue;
}
item_id = fields[1].GetUInt32();
if(!GetItemPrototype(item_id))
{
sLog.outErrorDb("Table `npc_vendor` for Vendor (Entry: %u) have in item list non-existed item (%u), ignore",entry,item_id);
continue;
}
VendorItemData& vList = m_mCacheVendorItemMap[entry];
ExtendedCost = fields[4].GetUInt32();
if(ExtendedCost && !sItemExtendedCostStore.LookupEntry(ExtendedCost))
{
sLog.outErrorDb("Table `npc_vendor` have Item (Entry: %u) with wrong ExtendedCost (%u) for vendor (%u), ignore",item_id,ExtendedCost,entry);
continue;
}
VendorItemList& vList = m_mCacheVendorItemMap[entry];
if(vList.size() >= MAX_VENDOR_ITEMS)
{
sLog.outErrorDb( "Table `npc_vendor` has too many items (%u >= %i) for vendor (Entry: %u), ignore", vList.size(), MAX_VENDOR_ITEMS, entry);
continue;
}
VendorItem* pVendorItem = new VendorItem();
pVendorItem->item = item_id;
pVendorItem->maxcount = fields[2].GetUInt32();
pVendorItem->incrtime = fields[3].GetUInt32();
pVendorItem->ExtendedCost = ExtendedCost;
vList.push_back(pVendorItem);
vList.AddItem(item_id,maxcount,incrtime,ExtendedCost);
++count;
} while (result->NextRow());
@@ -6838,6 +6856,109 @@ void ObjectMgr::LoadNpcTextId()
sLog.outString( ">> Loaded %d NpcTextId ", count );
}
void ObjectMgr::AddVendorItem( uint32 entry,uint32 item, uint32 maxcount, uint32 incrtime, uint32 extendedcost )
{
VendorItemData& vList = m_mCacheVendorItemMap[entry];
vList.AddItem(item,maxcount,incrtime,extendedcost);
WorldDatabase.PExecuteLog("INSERT INTO npc_vendor (entry,item,maxcount,incrtime,extendedcost) VALUES('%u','%u','%u','%u','%u')",entry, item, maxcount,incrtime,extendedcost);
}
bool ObjectMgr::RemoveVendorItem( uint32 entry,uint32 item )
{
CacheVendorItemMap::iterator iter = m_mCacheVendorItemMap.find(entry);
if(iter == m_mCacheVendorItemMap.end())
return false;
if(!iter->second.FindItem(item))
return false;
iter->second.RemoveItem(item);
WorldDatabase.PExecuteLog("DELETE FROM npc_vendor WHERE entry='%u' AND item='%u'",entry, item);
return true;
}
bool ObjectMgr::IsVendorItemValid( uint32 vendor_entry, uint32 item_id, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost, Player* pl ) const
{
CreatureInfo const* cInfo = GetCreatureTemplate(vendor_entry);
if(!cInfo)
{
if(pl)
ChatHandler(pl).SendSysMessage(LANG_COMMAND_VENDORSELECTION);
else
sLog.outErrorDb("Table `npc_vendor` have data for not existed creature template (Entry: %u), ignore", vendor_entry);
return false;
}
if(!(cInfo->npcflag & UNIT_NPC_FLAG_VENDOR))
{
if(pl)
ChatHandler(pl).SendSysMessage(LANG_COMMAND_VENDORSELECTION);
else
sLog.outErrorDb("Table `npc_vendor` have data for not creature template (Entry: %u) without vendor flag, ignore", vendor_entry);
return false;
}
if(!GetItemPrototype(item_id))
{
if(pl)
ChatHandler(pl).PSendSysMessage(LANG_ITEM_NOT_FOUND, item_id);
else
sLog.outErrorDb("Table `npc_vendor` for Vendor (Entry: %u) have in item list non-existed item (%u), ignore",vendor_entry,item_id);
return false;
}
if(ExtendedCost && !sItemExtendedCostStore.LookupEntry(ExtendedCost))
{
if(pl)
ChatHandler(pl).PSendSysMessage(LANG_EXTENDED_COST_NOT_EXIST,ExtendedCost);
else
sLog.outErrorDb("Table `npc_vendor` have Item (Entry: %u) with wrong ExtendedCost (%u) for vendor (%u), ignore",item_id,ExtendedCost,vendor_entry);
return false;
}
if(maxcount > 0 && incrtime == 0)
{
if(pl)
ChatHandler(pl).PSendSysMessage("MaxCount!=0 (%u) but IncrTime==0", maxcount);
else
sLog.outErrorDb( "Table `npc_vendor` has `maxcount` (%u) for item %u of vendor (Entry: %u) but `incrtime`=0, ignore", maxcount, item_id, vendor_entry);
return false;
}
else if(maxcount==0 && incrtime > 0)
{
if(pl)
ChatHandler(pl).PSendSysMessage("MaxCount==0 but IncrTime<>=0");
else
sLog.outErrorDb( "Table `npc_vendor` has `maxcount`=0 for item %u of vendor (Entry: %u) but `incrtime`<>0, ignore", item_id, vendor_entry);
return false;
}
VendorItemData const* vItems = GetNpcVendorItemList(vendor_entry);
if(!vItems)
return true; // later checks for non-empty lists
if(vItems->FindItem(item_id))
{
if(pl)
ChatHandler(pl).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST,item_id);
else
sLog.outErrorDb( "Table `npc_vendor` has duplicate items %u for vendor (Entry: %u), ignore", item_id, vendor_entry);
return false;
}
if(vItems->GetItemCount() >= MAX_VENDOR_ITEMS)
{
if(pl)
ChatHandler(pl).SendSysMessage(LANG_COMMAND_ADDVENDORITEMITEMS);
else
sLog.outErrorDb( "Table `npc_vendor` has too many items (%u >= %i) for vendor (Entry: %u), ignore", vItems->GetItemCount(), MAX_VENDOR_ITEMS, vendor_entry);
return false;
}
return true;
}
// Functions for scripting access
const char* GetAreaTriggerScriptNameById(uint32 id)
{
@@ -6848,7 +6969,7 @@ bool LoadMangosStrings(DatabaseType& db, char const* table,int32 start_value, in
{
if(start_value >= 0 || start_value <= end_value) // start/end reversed for negative values
{
sLog.outError("Table '%s' attempt loaded with invalid range (%d - %d), use (%d - %d) instead.",table,start_value,end_value,-1,std::numeric_limits<int32>::min());
sLog.outErrorDb("Table '%s' attempt loaded with invalid range (%d - %d), use (%d - %d) instead.",table,start_value,end_value,-1,std::numeric_limits<int32>::min());
start_value = -1;
end_value = std::numeric_limits<int32>::min();
}
+15 -12
View File
@@ -228,18 +228,8 @@ struct PlayerCondition
// NPC gossip text id
typedef HM_NAMESPACE::hash_map<uint32, uint32> CacheNpcTextIdMap;
// Vendors
struct VendorItem
{
uint32 item;
uint32 maxcount;
uint32 incrtime;
uint32 ExtendedCost;
};
typedef std::vector<VendorItem*> VendorItemList;
typedef HM_NAMESPACE::hash_map<uint32, VendorItemList> CacheVendorItemMap;
typedef HM_NAMESPACE::hash_map<uint32, VendorItemData> CacheVendorItemMap;
typedef HM_NAMESPACE::hash_map<uint32, TrainerSpellData> CacheTrainerSpellMap;
enum SkillRangeType
@@ -258,6 +248,16 @@ SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial);
bool normalizePlayerName(std::string& name);
struct MANGOS_DLL_SPEC LanguageDesc
{
Language lang_id;
uint32 spell_id;
uint32 skill_id;
};
extern LanguageDesc lang_description[LANGUAGES_COUNT];
MANGOS_DLL_SPEC LanguageDesc const* GetLanguageDescByID(uint32 lang);
class PlayerDumpReader;
class ObjectMgr
@@ -732,7 +732,7 @@ class ObjectMgr
return &iter->second;
}
VendorItemList const* GetNpcVendorItemList(uint32 entry) const
VendorItemData const* GetNpcVendorItemList(uint32 entry) const
{
CacheVendorItemMap::const_iterator iter = m_mCacheVendorItemMap.find(entry);
if(iter == m_mCacheVendorItemMap.end())
@@ -740,6 +740,9 @@ class ObjectMgr
return &iter->second;
}
void AddVendorItem(uint32 entry,uint32 item, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost);
bool RemoveVendorItem(uint32 entry,uint32 item);
bool IsVendorItemValid( uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL ) const;
protected:
uint32 m_auctionid;
uint32 m_mailid;
+1750 -1750
View File
File diff suppressed because it is too large Load Diff
+36 -19
View File
@@ -5794,7 +5794,7 @@ void Player::RewardReputation(Unit *pVictim, float rate)
if(!pVictim || pVictim->GetTypeId() == TYPEID_PLAYER)
return;
ReputationOnKillEntry const* Rep = objmgr.GetReputationOnKilEntry(pVictim->GetEntry());
ReputationOnKillEntry const* Rep = objmgr.GetReputationOnKilEntry(((Creature*)pVictim)->GetCreatureInfo()->Entry);
if(!Rep)
return;
@@ -16380,20 +16380,28 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
return false;
}
// load vendor items if not yet
pCreature->LoadGoods();
VendorItemData const* vItems = pCreature->GetVendorItems();
if(!vItems || vItems->Empty())
{
SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0);
return false;
}
CreatureItem* crItem = pCreature->FindItem(item);
VendorItem const* crItem = vItems->FindItem(item);
if(!crItem)
{
SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0);
return false;
}
if( crItem->maxcount != 0 && crItem->count < count )
// check current item amount if it limited
if( crItem->maxcount != 0 )
{
SendBuyError( BUY_ERR_ITEM_ALREADY_SOLD, pCreature, item, 0);
return false;
if(pCreature->GetVendorItemCurrentCount(crItem) < pProto->BuyCount * count )
{
SendBuyError( BUY_ERR_ITEM_ALREADY_SOLD, pCreature, item, 0);
return false;
}
}
if( uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank)
@@ -16508,17 +16516,16 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
if(Item *it = StoreNewItem( dest, item, true ))
{
if( crItem->maxcount != 0 )
crItem->count -= pProto->BuyCount * count;
uint32 new_count = pCreature->UpdateVendorItemCurrentCount(crItem,pProto->BuyCount * count);
WorldPacket data(SMSG_BUY_ITEM, (8+4+4+4));
data << pCreature->GetGUID();
data << (uint32)crItem->id; // entry
data << (uint32)crItem->count;
data << (uint32)crItem->item;
data << (uint32)(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF);
data << (uint32)count;
GetSession()->SendPacket(&data);
SendNewItem(it, count, true, false, false);
SendNewItem(it, pProto->BuyCount*count, true, false, false);
}
}
else if( IsEquipmentPos( bag, slot ) )
@@ -16548,17 +16555,16 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
if(Item *it = EquipNewItem( dest, item, pProto->BuyCount * count, true ))
{
if( crItem->maxcount != 0 )
crItem->count -= pProto->BuyCount * count;
uint32 new_count = pCreature->UpdateVendorItemCurrentCount(crItem,pProto->BuyCount * count);
WorldPacket data(SMSG_BUY_ITEM, (8+4+4+4));
data << pCreature->GetGUID();
data << (uint32)crItem->id; // entry
data << (uint32)crItem->count;
data << (uint32)crItem->item;
data << (uint32)(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF);
data << (uint32)count;
GetSession()->SendPacket(&data);
SendNewItem(it, count, true, false, false);
SendNewItem(it, pProto->BuyCount*count, true, false, false);
AutoUnequipOffhandIfNeed();
}
@@ -16569,7 +16575,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
return false;
}
return crItem->maxcount!=0?true:false;
return crItem->maxcount!=0;
}
uint32 Player::GetMaxPersonalArenaRatingRequirement()
@@ -17174,7 +17180,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
// set fly flag if in fly form or taxi flight to prevent visually drop at ground in showup moment
if(HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) || isInFlight())
SetUnitMovementFlags(GetUnitMovementFlags() | MOVEMENTFLAG_FLYING2);
AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
}
void Player::SendInitialPacketsAfterAddToMap()
@@ -18167,3 +18173,14 @@ bool ItemPosCount::isContainedIn(ItemPosCountVec const& vec) const
return false;
}
bool Player::isAllowUseBattleGroundObject()
{
return ( //InBattleGround() && // in battleground - not need, check in other cases
!IsMounted() && // not mounted
!HasStealthAura() && // not stealthed
!HasInvisibilityAura() && // not invisible
!HasAura(SPELL_RECENTLY_DROPPED_FLAG, 0) && // can't pickup
isAlive() // live player
);
}
+1
View File
@@ -1898,6 +1898,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void ClearAfkReports() { m_bgAfkReporter.clear(); }
bool GetBGAccessByLevel(uint32 bgTypeId) const;
bool isAllowUseBattleGroundObject();
/*********************************************************/
/*** REST SYSTEM ***/
+76 -73
View File
@@ -1,73 +1,76 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "PointMovementGenerator.h"
#include "Errors.h"
#include "Creature.h"
#include "CreatureAI.h"
#include "MapManager.h"
#include "DestinationHolderImp.h"
//----- Point Movement Generator
template<class T>
void PointMovementGenerator<T>::Initialize(T &unit)
{
unit.StopMoving();
Traveller<T> traveller(unit);
i_destinationHolder.SetDestination(traveller,i_x,i_y,i_z);
}
template<class T>
bool PointMovementGenerator<T>::Update(T &unit, const uint32 &diff)
{
if(!&unit)
return false;
if(unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED))
return true;
Traveller<T> traveller(unit);
i_destinationHolder.UpdateTraveller(traveller, diff, false);
if(i_destinationHolder.HasArrived())
{
unit.StopMoving();
MovementInform(unit);
return false;
}
return true;
}
template<class T>
void PointMovementGenerator<T>::MovementInform(T &unit)
{
}
template <> void PointMovementGenerator<Creature>::MovementInform(Creature &unit)
{
unit.AI()->MovementInform(POINT_MOTION_TYPE, id);
}
template void PointMovementGenerator<Player>::Initialize(Player&);
template bool PointMovementGenerator<Player>::Update(Player &, const uint32 &diff);
template void PointMovementGenerator<Player>::MovementInform(Player&);
template void PointMovementGenerator<Creature>::Initialize(Creature&);
template bool PointMovementGenerator<Creature>::Update(Creature&, const uint32 &diff);
/*
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "PointMovementGenerator.h"
#include "Errors.h"
#include "Creature.h"
#include "CreatureAI.h"
#include "MapManager.h"
#include "DestinationHolderImp.h"
//----- Point Movement Generator
template<class T>
void PointMovementGenerator<T>::Initialize(T &unit)
{
unit.StopMoving();
Traveller<T> traveller(unit);
i_destinationHolder.SetDestination(traveller,i_x,i_y,i_z);
if (unit.GetTypeId() == TYPEID_UNIT && ((Creature*)&unit)->canFly())
unit.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
}
template<class T>
bool PointMovementGenerator<T>::Update(T &unit, const uint32 &diff)
{
if(!&unit)
return false;
if(unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED))
return true;
Traveller<T> traveller(unit);
i_destinationHolder.UpdateTraveller(traveller, diff, false);
if(i_destinationHolder.HasArrived())
{
unit.StopMoving();
MovementInform(unit);
return false;
}
return true;
}
template<class T>
void PointMovementGenerator<T>::MovementInform(T &unit)
{
}
template <> void PointMovementGenerator<Creature>::MovementInform(Creature &unit)
{
unit.AI()->MovementInform(POINT_MOTION_TYPE, id);
}
template void PointMovementGenerator<Player>::Initialize(Player&);
template bool PointMovementGenerator<Player>::Update(Player &, const uint32 &diff);
template void PointMovementGenerator<Player>::MovementInform(Player&);
template void PointMovementGenerator<Creature>::Initialize(Creature&);
template bool PointMovementGenerator<Creature>::Update(Creature&, const uint32 &diff);
+200 -199
View File
@@ -1,199 +1,200 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "QuestDef.h"
#include "Player.h"
#include "World.h"
Quest::Quest(Field * questRecord)
{
QuestId = questRecord[0].GetUInt32();
ZoneOrSort = questRecord[1].GetInt32();
SkillOrClass = questRecord[2].GetInt32();
MinLevel = questRecord[3].GetUInt32();
QuestLevel = questRecord[4].GetUInt32();
Type = questRecord[5].GetUInt32();
RequiredRaces = questRecord[6].GetUInt32();
RequiredSkillValue = questRecord[7].GetUInt32();
RepObjectiveFaction = questRecord[8].GetUInt32();
RepObjectiveValue = questRecord[9].GetInt32();
RequiredMinRepFaction = questRecord[10].GetUInt32();
RequiredMinRepValue = questRecord[11].GetInt32();
RequiredMaxRepFaction = questRecord[12].GetUInt32();
RequiredMaxRepValue = questRecord[13].GetInt32();
SuggestedPlayers = questRecord[14].GetUInt32();
LimitTime = questRecord[15].GetUInt32();
QuestFlags = questRecord[16].GetUInt16();
uint32 SpecialFlags = questRecord[17].GetUInt16();
CharTitleId = questRecord[18].GetUInt32();
PrevQuestId = questRecord[19].GetInt32();
NextQuestId = questRecord[20].GetInt32();
ExclusiveGroup = questRecord[21].GetInt32();
NextQuestInChain = questRecord[22].GetUInt32();
SrcItemId = questRecord[23].GetUInt32();
SrcItemCount = questRecord[24].GetUInt32();
SrcSpell = questRecord[25].GetUInt32();
Title = questRecord[26].GetCppString();
Details = questRecord[27].GetCppString();
Objectives = questRecord[28].GetCppString();
OfferRewardText = questRecord[29].GetCppString();
RequestItemsText = questRecord[30].GetCppString();
EndText = questRecord[31].GetCppString();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
ObjectiveText[i] = questRecord[32+i].GetCppString();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
ReqItemId[i] = questRecord[36+i].GetUInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
ReqItemCount[i] = questRecord[40+i].GetUInt32();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
ReqSourceId[i] = questRecord[44+i].GetUInt32();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
ReqSourceCount[i] = questRecord[48+i].GetUInt32();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
ReqSourceRef[i] = questRecord[52+i].GetUInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
ReqCreatureOrGOId[i] = questRecord[56+i].GetInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
ReqCreatureOrGOCount[i] = questRecord[60+i].GetUInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
ReqSpell[i] = questRecord[64+i].GetUInt32();
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
RewChoiceItemId[i] = questRecord[68+i].GetUInt32();
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
RewChoiceItemCount[i] = questRecord[74+i].GetUInt32();
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
RewItemId[i] = questRecord[80+i].GetUInt32();
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
RewItemCount[i] = questRecord[84+i].GetUInt32();
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
RewRepFaction[i] = questRecord[88+i].GetUInt32();
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
RewRepValue[i] = questRecord[93+i].GetInt32();
RewOrReqMoney = questRecord[98].GetInt32();
RewMoneyMaxLevel = questRecord[99].GetUInt32();
RewSpell = questRecord[100].GetUInt32();
RewSpellCast = questRecord[101].GetUInt32();
RewMailTemplateId = questRecord[102].GetUInt32();
RewMailDelaySecs = questRecord[103].GetUInt32();
PointMapId = questRecord[104].GetUInt32();
PointX = questRecord[105].GetFloat();
PointY = questRecord[106].GetFloat();
PointOpt = questRecord[107].GetUInt32();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
DetailsEmote[i] = questRecord[108+i].GetUInt32();
IncompleteEmote = questRecord[112].GetUInt32();
CompleteEmote = questRecord[113].GetUInt32();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
OfferRewardEmote[i] = questRecord[114+i].GetInt32();
QuestStartScript = questRecord[118].GetUInt32();
QuestCompleteScript = questRecord[119].GetUInt32();
QuestFlags |= SpecialFlags << 16;
m_reqitemscount = 0;
m_reqCreatureOrGOcount = 0;
m_rewitemscount = 0;
m_rewchoiceitemscount = 0;
for (int i=0; i < QUEST_OBJECTIVES_COUNT; i++)
{
if ( ReqItemId[i] )
++m_reqitemscount;
if ( ReqCreatureOrGOId[i] )
++m_reqCreatureOrGOcount;
}
for (int i=0; i < QUEST_REWARDS_COUNT; i++)
{
if ( RewItemId[i] )
++m_rewitemscount;
}
for (int i=0; i < QUEST_REWARD_CHOICES_COUNT; i++)
{
if (RewChoiceItemId[i])
++m_rewchoiceitemscount;
}
}
uint32 Quest::XPValue( Player *pPlayer ) const
{
if( pPlayer )
{
if( RewMoneyMaxLevel > 0 )
{
uint32 pLevel = pPlayer->getLevel();
uint32 qLevel = QuestLevel;
float fullxp = 0;
if (qLevel >= 65)
fullxp = RewMoneyMaxLevel / 6.0f;
else if (qLevel == 64)
fullxp = RewMoneyMaxLevel / 4.8f;
else if (qLevel == 63)
fullxp = RewMoneyMaxLevel / 3.6f;
else if (qLevel == 62)
fullxp = RewMoneyMaxLevel / 2.4f;
else if (qLevel == 61)
fullxp = RewMoneyMaxLevel / 1.2f;
else if (qLevel > 0 && qLevel <= 60)
fullxp = RewMoneyMaxLevel / 0.6f;
if( pLevel <= qLevel + 5 )
return (uint32)fullxp;
else if( pLevel == qLevel + 6 )
return (uint32)(fullxp * 0.8f);
else if( pLevel == qLevel + 7 )
return (uint32)(fullxp * 0.6f);
else if( pLevel == qLevel + 8 )
return (uint32)(fullxp * 0.4f);
else if( pLevel == qLevel + 9 )
return (uint32)(fullxp * 0.2f);
else
return (uint32)(fullxp * 0.1f);
}
}
return 0;
}
int32 Quest::GetRewOrReqMoney() const
{
if(RewOrReqMoney <=0)
return RewOrReqMoney;
return int32(RewOrReqMoney * sWorld.getRate(RATE_DROP_MONEY));
}
/*
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "QuestDef.h"
#include "Player.h"
#include "World.h"
Quest::Quest(Field * questRecord)
{
QuestId = questRecord[0].GetUInt32();
QuestMethod = questRecord[1].GetUInt32();
ZoneOrSort = questRecord[2].GetInt32();
SkillOrClass = questRecord[3].GetInt32();
MinLevel = questRecord[4].GetUInt32();
QuestLevel = questRecord[5].GetUInt32();
Type = questRecord[6].GetUInt32();
RequiredRaces = questRecord[7].GetUInt32();
RequiredSkillValue = questRecord[8].GetUInt32();
RepObjectiveFaction = questRecord[9].GetUInt32();
RepObjectiveValue = questRecord[10].GetInt32();
RequiredMinRepFaction = questRecord[11].GetUInt32();
RequiredMinRepValue = questRecord[12].GetInt32();
RequiredMaxRepFaction = questRecord[13].GetUInt32();
RequiredMaxRepValue = questRecord[14].GetInt32();
SuggestedPlayers = questRecord[15].GetUInt32();
LimitTime = questRecord[16].GetUInt32();
QuestFlags = questRecord[17].GetUInt16();
uint32 SpecialFlags = questRecord[18].GetUInt16();
CharTitleId = questRecord[19].GetUInt32();
PrevQuestId = questRecord[20].GetInt32();
NextQuestId = questRecord[21].GetInt32();
ExclusiveGroup = questRecord[22].GetInt32();
NextQuestInChain = questRecord[23].GetUInt32();
SrcItemId = questRecord[24].GetUInt32();
SrcItemCount = questRecord[25].GetUInt32();
SrcSpell = questRecord[26].GetUInt32();
Title = questRecord[27].GetCppString();
Details = questRecord[28].GetCppString();
Objectives = questRecord[29].GetCppString();
OfferRewardText = questRecord[30].GetCppString();
RequestItemsText = questRecord[31].GetCppString();
EndText = questRecord[32].GetCppString();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
ObjectiveText[i] = questRecord[33+i].GetCppString();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
ReqItemId[i] = questRecord[37+i].GetUInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
ReqItemCount[i] = questRecord[41+i].GetUInt32();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
ReqSourceId[i] = questRecord[45+i].GetUInt32();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
ReqSourceCount[i] = questRecord[49+i].GetUInt32();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
ReqSourceRef[i] = questRecord[53+i].GetUInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
ReqCreatureOrGOId[i] = questRecord[57+i].GetInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
ReqCreatureOrGOCount[i] = questRecord[61+i].GetUInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
ReqSpell[i] = questRecord[65+i].GetUInt32();
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
RewChoiceItemId[i] = questRecord[69+i].GetUInt32();
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
RewChoiceItemCount[i] = questRecord[75+i].GetUInt32();
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
RewItemId[i] = questRecord[81+i].GetUInt32();
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
RewItemCount[i] = questRecord[85+i].GetUInt32();
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
RewRepFaction[i] = questRecord[89+i].GetUInt32();
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
RewRepValue[i] = questRecord[94+i].GetInt32();
RewOrReqMoney = questRecord[99].GetInt32();
RewMoneyMaxLevel = questRecord[100].GetUInt32();
RewSpell = questRecord[101].GetUInt32();
RewSpellCast = questRecord[102].GetUInt32();
RewMailTemplateId = questRecord[103].GetUInt32();
RewMailDelaySecs = questRecord[104].GetUInt32();
PointMapId = questRecord[105].GetUInt32();
PointX = questRecord[106].GetFloat();
PointY = questRecord[107].GetFloat();
PointOpt = questRecord[108].GetUInt32();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
DetailsEmote[i] = questRecord[109+i].GetUInt32();
IncompleteEmote = questRecord[113].GetUInt32();
CompleteEmote = questRecord[114].GetUInt32();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
OfferRewardEmote[i] = questRecord[115+i].GetInt32();
QuestStartScript = questRecord[119].GetUInt32();
QuestCompleteScript = questRecord[120].GetUInt32();
QuestFlags |= SpecialFlags << 16;
m_reqitemscount = 0;
m_reqCreatureOrGOcount = 0;
m_rewitemscount = 0;
m_rewchoiceitemscount = 0;
for (int i=0; i < QUEST_OBJECTIVES_COUNT; i++)
{
if ( ReqItemId[i] )
++m_reqitemscount;
if ( ReqCreatureOrGOId[i] )
++m_reqCreatureOrGOcount;
}
for (int i=0; i < QUEST_REWARDS_COUNT; i++)
{
if ( RewItemId[i] )
++m_rewitemscount;
}
for (int i=0; i < QUEST_REWARD_CHOICES_COUNT; i++)
{
if (RewChoiceItemId[i])
++m_rewchoiceitemscount;
}
}
uint32 Quest::XPValue( Player *pPlayer ) const
{
if( pPlayer )
{
if( RewMoneyMaxLevel > 0 )
{
uint32 pLevel = pPlayer->getLevel();
uint32 qLevel = QuestLevel;
float fullxp = 0;
if (qLevel >= 65)
fullxp = RewMoneyMaxLevel / 6.0f;
else if (qLevel == 64)
fullxp = RewMoneyMaxLevel / 4.8f;
else if (qLevel == 63)
fullxp = RewMoneyMaxLevel / 3.6f;
else if (qLevel == 62)
fullxp = RewMoneyMaxLevel / 2.4f;
else if (qLevel == 61)
fullxp = RewMoneyMaxLevel / 1.2f;
else if (qLevel > 0 && qLevel <= 60)
fullxp = RewMoneyMaxLevel / 0.6f;
if( pLevel <= qLevel + 5 )
return (uint32)fullxp;
else if( pLevel == qLevel + 6 )
return (uint32)(fullxp * 0.8f);
else if( pLevel == qLevel + 7 )
return (uint32)(fullxp * 0.6f);
else if( pLevel == qLevel + 8 )
return (uint32)(fullxp * 0.4f);
else if( pLevel == qLevel + 9 )
return (uint32)(fullxp * 0.2f);
else
return (uint32)(fullxp * 0.1f);
}
}
return 0;
}
int32 Quest::GetRewOrReqMoney() const
{
if(RewOrReqMoney <=0)
return RewOrReqMoney;
return int32(RewOrReqMoney * sWorld.getRate(RATE_DROP_MONEY));
}
+332 -330
View File
@@ -1,330 +1,332 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef MANGOSSERVER_QUEST_H
#define MANGOSSERVER_QUEST_H
#include "Platform/Define.h"
#include "Database/DatabaseEnv.h"
#include <string>
#include <vector>
class Player;
class ObjectMgr;
#define MAX_QUEST_LOG_SIZE 25
#define QUEST_OBJECTIVES_COUNT 4
#define QUEST_SOURCE_ITEM_IDS_COUNT 4
#define QUEST_REWARD_CHOICES_COUNT 6
#define QUEST_REWARDS_COUNT 4
#define QUEST_DEPLINK_COUNT 10
#define QUEST_REPUTATIONS_COUNT 5
#define QUEST_EMOTE_COUNT 4
enum QuestFailedReasons
{
INVALIDREASON_DONT_HAVE_REQ = 0,
INVALIDREASON_QUEST_FAILED_LOW_LEVEL = 1, //You are not high enough level for that quest.
INVALIDREASON_QUEST_FAILED_WRONG_RACE = 6, //That quest is not available to your race.
INVALIDREASON_QUEST_ALREADY_DONE = 7, //You have completed that quest.
INVALIDREASON_QUEST_ONLY_ONE_TIMED = 12, //You can only be on one timed quest at a time.
INVALIDREASON_QUEST_ALREADY_ON = 13, //You are already on that quest
INVALIDREASON_QUEST_FAILED_EXPANSION = 16, //This quest requires an expansion enabled account.
INVALIDREASON_QUEST_ALREADY_ON2 = 18, //You are already on that quest
INVALIDREASON_QUEST_FAILED_MISSING_ITEMS = 21, //You don't have the required items with you. Check storage.
INVALIDREASON_QUEST_FAILED_NOT_ENOUGH_MONEY = 23, //You don't have enough money for that quest.
INVALIDREASON_DAILY_QUESTS_REMAINING = 26, //You have already completed 10 daily quests today
INVALIDREASON_QUEST_FAILED_CAIS = 27, //You cannot complete quests once you have reached tired time
};
enum QuestShareMessages
{
QUEST_PARTY_MSG_SHARING_QUEST = 0,
QUEST_PARTY_MSG_CANT_TAKE_QUEST = 1,
QUEST_PARTY_MSG_ACCEPT_QUEST = 2,
QUEST_PARTY_MSG_REFUSE_QUEST = 3,
QUEST_PARTY_MSG_TOO_FAR = 4,
QUEST_PARTY_MSG_BUSY = 5,
QUEST_PARTY_MSG_LOG_FULL = 6,
QUEST_PARTY_MSG_HAVE_QUEST = 7,
QUEST_PARTY_MSG_FINISH_QUEST = 8,
};
enum __QuestTradeSkill
{
QUEST_TRSKILL_NONE = 0,
QUEST_TRSKILL_ALCHEMY = 1,
QUEST_TRSKILL_BLACKSMITHING = 2,
QUEST_TRSKILL_COOKING = 3,
QUEST_TRSKILL_ENCHANTING = 4,
QUEST_TRSKILL_ENGINEERING = 5,
QUEST_TRSKILL_FIRSTAID = 6,
QUEST_TRSKILL_HERBALISM = 7,
QUEST_TRSKILL_LEATHERWORKING = 8,
QUEST_TRSKILL_POISONS = 9,
QUEST_TRSKILL_TAILORING = 10,
QUEST_TRSKILL_MINING = 11,
QUEST_TRSKILL_FISHING = 12,
QUEST_TRSKILL_SKINNING = 13,
QUEST_TRSKILL_JEWELCRAFTING = 14,
};
enum QuestStatus
{
QUEST_STATUS_NONE = 0,
QUEST_STATUS_COMPLETE = 1,
QUEST_STATUS_UNAVAILABLE = 2,
QUEST_STATUS_INCOMPLETE = 3,
QUEST_STATUS_AVAILABLE = 4,
MAX_QUEST_STATUS
};
enum __QuestGiverStatus
{
DIALOG_STATUS_NONE = 0,
DIALOG_STATUS_UNAVAILABLE = 1,
DIALOG_STATUS_CHAT = 2,
DIALOG_STATUS_INCOMPLETE = 3,
DIALOG_STATUS_REWARD_REP = 4,
DIALOG_STATUS_AVAILABLE_REP = 5,
DIALOG_STATUS_AVAILABLE = 6,
DIALOG_STATUS_REWARD2 = 7, // not yellow dot on minimap
DIALOG_STATUS_REWARD = 8 // yellow dot on minimap
};
enum __QuestFlags
{
// Flags used at server and sended to client
QUEST_FLAGS_STAY_ALIVE = 1, // Not used currently
QUEST_FLAGS_EVENT = 2, // Not used currently
QUEST_FLAGS_EXPLORATION = 4, // Not used currently
QUEST_FLAGS_SHARABLE = 8, // Can be shared: Player::CanShareQuest()
//QUEST_FLAGS_NONE2 = 16, // Not used currently
QUEST_FLAGS_EPIC = 32, // Not used currently: Unsure of content
QUEST_FLAGS_RAID = 64, // Not used currently
QUEST_FLAGS_TBC = 128, // Not used currently: Available if TBC expension enabled only
QUEST_FLAGS_UNK2 = 256, // Not used currently: _DELIVER_MORE Quest needs more than normal _q-item_ drops from mobs
QUEST_FLAGS_HIDDEN_REWARDS = 512, // Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUESTGIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE))
QUEST_FLAGS_AUTO_REWARDED = 1024, // These quests are automatically rewarded on quest complete and they will never appear in quest log client side.
QUEST_FLAGS_TBC_RACES = 2048, // Not used currently: Bloodelf/draenei starting zone quests
QUEST_FLAGS_DAILY = 4096, // Used to know quest is Daily one
// Mangos flags for set SpecialFlags in DB if required but used only at server
QUEST_MANGOS_FLAGS_REPEATABLE = 0x010000, // Set by 1 in SpecialFlags from DB
QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT = 0x020000, // Set by 2 in SpecialFlags from DB (if reequired area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script DLL)
QUEST_MANGOS_FLAGS_DB_ALLOWED = 0xFFFF | QUEST_MANGOS_FLAGS_REPEATABLE | QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT,
// Mangos flags for internal use only
QUEST_MANGOS_FLAGS_DELIVER = 0x040000, // Internal flag computed only
QUEST_MANGOS_FLAGS_SPEAKTO = 0x080000, // Internal flag computed only
QUEST_MANGOS_FLAGS_KILL_OR_CAST = 0x100000, // Internal flag computed only
QUEST_MANGOS_FLAGS_TIMED = 0x200000, // Internal flag computed only
};
struct QuestLocale
{
QuestLocale() { ObjectiveText.resize(QUEST_OBJECTIVES_COUNT); }
std::vector<std::string> Title;
std::vector<std::string> Details;
std::vector<std::string> Objectives;
std::vector<std::string> OfferRewardText;
std::vector<std::string> RequestItemsText;
std::vector<std::string> EndText;
std::vector< std::vector<std::string> > ObjectiveText;
};
// This Quest class provides a convenient way to access a few pretotaled (cached) quest details,
// all base quest information, and any utility functions such as generating the amount of
// xp to give
class Quest
{
friend class ObjectMgr;
public:
Quest(Field * questRecord);
uint32 XPValue( Player *pPlayer ) const;
bool HasFlag( uint32 flag ) const { return ( QuestFlags & flag ) != 0; }
void SetFlag( uint32 flag ) { QuestFlags |= flag; }
// table data accessors:
uint32 GetQuestId() const { return QuestId; }
int32 GetZoneOrSort() const { return ZoneOrSort; }
int32 GetSkillOrClass() const { return SkillOrClass; }
uint32 GetMinLevel() const { return MinLevel; }
uint32 GetQuestLevel() const { return QuestLevel; }
uint32 GetType() const { return Type; }
uint32 GetRequiredRaces() const { return RequiredRaces; }
uint32 GetRequiredSkillValue() const { return RequiredSkillValue; }
uint32 GetRepObjectiveFaction() const { return RepObjectiveFaction; }
int32 GetRepObjectiveValue() const { return RepObjectiveValue; }
uint32 GetRequiredMinRepFaction() const { return RequiredMinRepFaction; }
int32 GetRequiredMinRepValue() const { return RequiredMinRepValue; }
uint32 GetRequiredMaxRepFaction() const { return RequiredMaxRepFaction; }
int32 GetRequiredMaxRepValue() const { return RequiredMaxRepValue; }
uint32 GetSuggestedPlayers() const { return SuggestedPlayers; }
uint32 GetLimitTime() const { return LimitTime; }
int32 GetPrevQuestId() const { return PrevQuestId; }
int32 GetNextQuestId() const { return NextQuestId; }
int32 GetExclusiveGroup() const { return ExclusiveGroup; }
uint32 GetNextQuestInChain() const { return NextQuestInChain; }
uint32 GetCharTitleId() const { return CharTitleId; }
uint32 GetSrcItemId() const { return SrcItemId; }
uint32 GetSrcItemCount() const { return SrcItemCount; }
uint32 GetSrcSpell() const { return SrcSpell; }
std::string GetTitle() const { return Title; }
std::string GetDetails() const { return Details; }
std::string GetObjectives() const { return Objectives; }
std::string GetOfferRewardText() const { return OfferRewardText; }
std::string GetRequestItemsText() const { return RequestItemsText; }
std::string GetEndText() const { return EndText; }
int32 GetRewOrReqMoney() const;
uint32 GetRewMoneyMaxLevel() const { return RewMoneyMaxLevel; }
// use in XP calculation at client
uint32 GetRewSpell() const { return RewSpell; }
uint32 GetRewSpellCast() const { return RewSpellCast; }
uint32 GetRewMailTemplateId() const { return RewMailTemplateId; }
uint32 GetRewMailDelaySecs() const { return RewMailDelaySecs; }
uint32 GetPointMapId() const { return PointMapId; }
float GetPointX() const { return PointX; }
float GetPointY() const { return PointY; }
uint32 GetPointOpt() const { return PointOpt; }
uint32 GetIncompleteEmote() const { return IncompleteEmote; }
uint32 GetCompleteEmote() const { return CompleteEmote; }
uint32 GetQuestStartScript() const { return QuestStartScript; }
uint32 GetQuestCompleteScript() const { return QuestCompleteScript; }
bool IsRepeatable() const { return QuestFlags & QUEST_MANGOS_FLAGS_REPEATABLE; }
bool IsAutoComplete() const { return Objectives.empty(); }
uint32 GetFlags() const { return QuestFlags; }
bool IsDaily() const { return QuestFlags & QUEST_FLAGS_DAILY; }
// multiple values
std::string ObjectiveText[QUEST_OBJECTIVES_COUNT];
uint32 ReqItemId[QUEST_OBJECTIVES_COUNT];
uint32 ReqItemCount[QUEST_OBJECTIVES_COUNT];
uint32 ReqSourceId[QUEST_SOURCE_ITEM_IDS_COUNT];
uint32 ReqSourceCount[QUEST_SOURCE_ITEM_IDS_COUNT];
uint32 ReqSourceRef[QUEST_SOURCE_ITEM_IDS_COUNT];
int32 ReqCreatureOrGOId[QUEST_OBJECTIVES_COUNT]; // >0 Creature <0 Gameobject
uint32 ReqCreatureOrGOCount[QUEST_OBJECTIVES_COUNT];
uint32 ReqSpell[QUEST_OBJECTIVES_COUNT];
uint32 RewChoiceItemId[QUEST_REWARD_CHOICES_COUNT];
uint32 RewChoiceItemCount[QUEST_REWARD_CHOICES_COUNT];
uint32 RewItemId[QUEST_REWARDS_COUNT];
uint32 RewItemCount[QUEST_REWARDS_COUNT];
uint32 RewRepFaction[QUEST_REPUTATIONS_COUNT];
int32 RewRepValue[QUEST_REPUTATIONS_COUNT];
uint32 DetailsEmote[QUEST_EMOTE_COUNT];
uint32 OfferRewardEmote[QUEST_EMOTE_COUNT];
uint32 GetReqItemsCount() const { return m_reqitemscount; }
uint32 GetReqCreatureOrGOcount() const { return m_reqCreatureOrGOcount; }
uint32 GetRewChoiceItemsCount() const { return m_rewchoiceitemscount; }
uint32 GetRewItemsCount() const { return m_rewitemscount; }
typedef std::vector<int32> PrevQuests;
PrevQuests prevQuests;
typedef std::vector<uint32> PrevChainQuests;
PrevChainQuests prevChainQuests;
// cached data
private:
uint32 m_reqitemscount;
uint32 m_reqCreatureOrGOcount;
uint32 m_rewchoiceitemscount;
uint32 m_rewitemscount;
// table data
protected:
uint32 QuestId;
int32 ZoneOrSort;
int32 SkillOrClass;
uint32 MinLevel;
uint32 QuestLevel;
uint32 Type;
uint32 RequiredRaces;
uint32 RequiredSkillValue;
uint32 RepObjectiveFaction;
int32 RepObjectiveValue;
uint32 RequiredMinRepFaction;
int32 RequiredMinRepValue;
uint32 RequiredMaxRepFaction;
int32 RequiredMaxRepValue;
uint32 SuggestedPlayers;
uint32 LimitTime;
uint32 QuestFlags;
uint32 CharTitleId;
int32 PrevQuestId;
int32 NextQuestId;
int32 ExclusiveGroup;
uint32 NextQuestInChain;
uint32 SrcItemId;
uint32 SrcItemCount;
uint32 SrcSpell;
std::string Title;
std::string Details;
std::string Objectives;
std::string OfferRewardText;
std::string RequestItemsText;
std::string EndText;
int32 RewOrReqMoney;
uint32 RewMoneyMaxLevel;
uint32 RewSpell;
uint32 RewSpellCast;
uint32 RewMailTemplateId;
uint32 RewMailDelaySecs;
uint32 PointMapId;
float PointX;
float PointY;
uint32 PointOpt;
uint32 IncompleteEmote;
uint32 CompleteEmote;
uint32 QuestStartScript;
uint32 QuestCompleteScript;
};
enum QuestUpdateState
{
QUEST_UNCHANGED = 0,
QUEST_CHANGED = 1,
QUEST_NEW = 2
};
struct QuestStatusData
{
QuestStatusData()
: m_status(QUEST_STATUS_NONE),m_rewarded(false),
m_explored(false), m_timer(0), uState(QUEST_NEW)
{
memset(m_itemcount, 0, QUEST_OBJECTIVES_COUNT * sizeof(uint32));
memset(m_creatureOrGOcount, 0, QUEST_OBJECTIVES_COUNT * sizeof(uint32));
}
QuestStatus m_status;
bool m_rewarded;
bool m_explored;
uint32 m_timer;
QuestUpdateState uState;
uint32 m_itemcount[ QUEST_OBJECTIVES_COUNT ];
uint32 m_creatureOrGOcount[ QUEST_OBJECTIVES_COUNT ];
};
#endif
/*
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef MANGOSSERVER_QUEST_H
#define MANGOSSERVER_QUEST_H
#include "Platform/Define.h"
#include "Database/DatabaseEnv.h"
#include <string>
#include <vector>
class Player;
class ObjectMgr;
#define MAX_QUEST_LOG_SIZE 25
#define QUEST_OBJECTIVES_COUNT 4
#define QUEST_SOURCE_ITEM_IDS_COUNT 4
#define QUEST_REWARD_CHOICES_COUNT 6
#define QUEST_REWARDS_COUNT 4
#define QUEST_DEPLINK_COUNT 10
#define QUEST_REPUTATIONS_COUNT 5
#define QUEST_EMOTE_COUNT 4
enum QuestFailedReasons
{
INVALIDREASON_DONT_HAVE_REQ = 0,
INVALIDREASON_QUEST_FAILED_LOW_LEVEL = 1, //You are not high enough level for that quest.
INVALIDREASON_QUEST_FAILED_WRONG_RACE = 6, //That quest is not available to your race.
INVALIDREASON_QUEST_ALREADY_DONE = 7, //You have completed that quest.
INVALIDREASON_QUEST_ONLY_ONE_TIMED = 12, //You can only be on one timed quest at a time.
INVALIDREASON_QUEST_ALREADY_ON = 13, //You are already on that quest
INVALIDREASON_QUEST_FAILED_EXPANSION = 16, //This quest requires an expansion enabled account.
INVALIDREASON_QUEST_ALREADY_ON2 = 18, //You are already on that quest
INVALIDREASON_QUEST_FAILED_MISSING_ITEMS = 21, //You don't have the required items with you. Check storage.
INVALIDREASON_QUEST_FAILED_NOT_ENOUGH_MONEY = 23, //You don't have enough money for that quest.
INVALIDREASON_DAILY_QUESTS_REMAINING = 26, //You have already completed 10 daily quests today
INVALIDREASON_QUEST_FAILED_CAIS = 27, //You cannot complete quests once you have reached tired time
};
enum QuestShareMessages
{
QUEST_PARTY_MSG_SHARING_QUEST = 0,
QUEST_PARTY_MSG_CANT_TAKE_QUEST = 1,
QUEST_PARTY_MSG_ACCEPT_QUEST = 2,
QUEST_PARTY_MSG_REFUSE_QUEST = 3,
QUEST_PARTY_MSG_TOO_FAR = 4,
QUEST_PARTY_MSG_BUSY = 5,
QUEST_PARTY_MSG_LOG_FULL = 6,
QUEST_PARTY_MSG_HAVE_QUEST = 7,
QUEST_PARTY_MSG_FINISH_QUEST = 8,
};
enum __QuestTradeSkill
{
QUEST_TRSKILL_NONE = 0,
QUEST_TRSKILL_ALCHEMY = 1,
QUEST_TRSKILL_BLACKSMITHING = 2,
QUEST_TRSKILL_COOKING = 3,
QUEST_TRSKILL_ENCHANTING = 4,
QUEST_TRSKILL_ENGINEERING = 5,
QUEST_TRSKILL_FIRSTAID = 6,
QUEST_TRSKILL_HERBALISM = 7,
QUEST_TRSKILL_LEATHERWORKING = 8,
QUEST_TRSKILL_POISONS = 9,
QUEST_TRSKILL_TAILORING = 10,
QUEST_TRSKILL_MINING = 11,
QUEST_TRSKILL_FISHING = 12,
QUEST_TRSKILL_SKINNING = 13,
QUEST_TRSKILL_JEWELCRAFTING = 14,
};
enum QuestStatus
{
QUEST_STATUS_NONE = 0,
QUEST_STATUS_COMPLETE = 1,
QUEST_STATUS_UNAVAILABLE = 2,
QUEST_STATUS_INCOMPLETE = 3,
QUEST_STATUS_AVAILABLE = 4,
MAX_QUEST_STATUS
};
enum __QuestGiverStatus
{
DIALOG_STATUS_NONE = 0,
DIALOG_STATUS_UNAVAILABLE = 1,
DIALOG_STATUS_CHAT = 2,
DIALOG_STATUS_INCOMPLETE = 3,
DIALOG_STATUS_REWARD_REP = 4,
DIALOG_STATUS_AVAILABLE_REP = 5,
DIALOG_STATUS_AVAILABLE = 6,
DIALOG_STATUS_REWARD2 = 7, // not yellow dot on minimap
DIALOG_STATUS_REWARD = 8 // yellow dot on minimap
};
enum __QuestFlags
{
// Flags used at server and sended to client
QUEST_FLAGS_STAY_ALIVE = 1, // Not used currently
QUEST_FLAGS_PARTY_ACCEPT = 2, // Not used currently. If player in party, all players that can accept this quest will receive confirmation box to accept quest CMSG_QUEST_CONFIRM_ACCEPT/SMSG_QUEST_CONFIRM_ACCEPT
QUEST_FLAGS_EXPLORATION = 4, // Not used currently
QUEST_FLAGS_SHARABLE = 8, // Can be shared: Player::CanShareQuest()
//QUEST_FLAGS_NONE2 = 16, // Not used currently
QUEST_FLAGS_EPIC = 32, // Not used currently: Unsure of content
QUEST_FLAGS_RAID = 64, // Not used currently
QUEST_FLAGS_TBC = 128, // Not used currently: Available if TBC expension enabled only
QUEST_FLAGS_UNK2 = 256, // Not used currently: _DELIVER_MORE Quest needs more than normal _q-item_ drops from mobs
QUEST_FLAGS_HIDDEN_REWARDS = 512, // Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUESTGIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE))
QUEST_FLAGS_AUTO_REWARDED = 1024, // These quests are automatically rewarded on quest complete and they will never appear in quest log client side.
QUEST_FLAGS_TBC_RACES = 2048, // Not used currently: Bloodelf/draenei starting zone quests
QUEST_FLAGS_DAILY = 4096, // Used to know quest is Daily one
// Mangos flags for set SpecialFlags in DB if required but used only at server
QUEST_MANGOS_FLAGS_REPEATABLE = 0x010000, // Set by 1 in SpecialFlags from DB
QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT = 0x020000, // Set by 2 in SpecialFlags from DB (if reequired area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script DLL)
QUEST_MANGOS_FLAGS_DB_ALLOWED = 0xFFFF | QUEST_MANGOS_FLAGS_REPEATABLE | QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT,
// Mangos flags for internal use only
QUEST_MANGOS_FLAGS_DELIVER = 0x040000, // Internal flag computed only
QUEST_MANGOS_FLAGS_SPEAKTO = 0x080000, // Internal flag computed only
QUEST_MANGOS_FLAGS_KILL_OR_CAST = 0x100000, // Internal flag computed only
QUEST_MANGOS_FLAGS_TIMED = 0x200000, // Internal flag computed only
};
struct QuestLocale
{
QuestLocale() { ObjectiveText.resize(QUEST_OBJECTIVES_COUNT); }
std::vector<std::string> Title;
std::vector<std::string> Details;
std::vector<std::string> Objectives;
std::vector<std::string> OfferRewardText;
std::vector<std::string> RequestItemsText;
std::vector<std::string> EndText;
std::vector< std::vector<std::string> > ObjectiveText;
};
// This Quest class provides a convenient way to access a few pretotaled (cached) quest details,
// all base quest information, and any utility functions such as generating the amount of
// xp to give
class Quest
{
friend class ObjectMgr;
public:
Quest(Field * questRecord);
uint32 XPValue( Player *pPlayer ) const;
bool HasFlag( uint32 flag ) const { return ( QuestFlags & flag ) != 0; }
void SetFlag( uint32 flag ) { QuestFlags |= flag; }
// table data accessors:
uint32 GetQuestId() const { return QuestId; }
uint32 GetQuestMethod() const { return QuestMethod; }
int32 GetZoneOrSort() const { return ZoneOrSort; }
int32 GetSkillOrClass() const { return SkillOrClass; }
uint32 GetMinLevel() const { return MinLevel; }
uint32 GetQuestLevel() const { return QuestLevel; }
uint32 GetType() const { return Type; }
uint32 GetRequiredRaces() const { return RequiredRaces; }
uint32 GetRequiredSkillValue() const { return RequiredSkillValue; }
uint32 GetRepObjectiveFaction() const { return RepObjectiveFaction; }
int32 GetRepObjectiveValue() const { return RepObjectiveValue; }
uint32 GetRequiredMinRepFaction() const { return RequiredMinRepFaction; }
int32 GetRequiredMinRepValue() const { return RequiredMinRepValue; }
uint32 GetRequiredMaxRepFaction() const { return RequiredMaxRepFaction; }
int32 GetRequiredMaxRepValue() const { return RequiredMaxRepValue; }
uint32 GetSuggestedPlayers() const { return SuggestedPlayers; }
uint32 GetLimitTime() const { return LimitTime; }
int32 GetPrevQuestId() const { return PrevQuestId; }
int32 GetNextQuestId() const { return NextQuestId; }
int32 GetExclusiveGroup() const { return ExclusiveGroup; }
uint32 GetNextQuestInChain() const { return NextQuestInChain; }
uint32 GetCharTitleId() const { return CharTitleId; }
uint32 GetSrcItemId() const { return SrcItemId; }
uint32 GetSrcItemCount() const { return SrcItemCount; }
uint32 GetSrcSpell() const { return SrcSpell; }
std::string GetTitle() const { return Title; }
std::string GetDetails() const { return Details; }
std::string GetObjectives() const { return Objectives; }
std::string GetOfferRewardText() const { return OfferRewardText; }
std::string GetRequestItemsText() const { return RequestItemsText; }
std::string GetEndText() const { return EndText; }
int32 GetRewOrReqMoney() const;
uint32 GetRewMoneyMaxLevel() const { return RewMoneyMaxLevel; }
// use in XP calculation at client
uint32 GetRewSpell() const { return RewSpell; }
uint32 GetRewSpellCast() const { return RewSpellCast; }
uint32 GetRewMailTemplateId() const { return RewMailTemplateId; }
uint32 GetRewMailDelaySecs() const { return RewMailDelaySecs; }
uint32 GetPointMapId() const { return PointMapId; }
float GetPointX() const { return PointX; }
float GetPointY() const { return PointY; }
uint32 GetPointOpt() const { return PointOpt; }
uint32 GetIncompleteEmote() const { return IncompleteEmote; }
uint32 GetCompleteEmote() const { return CompleteEmote; }
uint32 GetQuestStartScript() const { return QuestStartScript; }
uint32 GetQuestCompleteScript() const { return QuestCompleteScript; }
bool IsRepeatable() const { return QuestFlags & QUEST_MANGOS_FLAGS_REPEATABLE; }
bool IsAutoComplete() const { return QuestMethod ? false : true; }
uint32 GetFlags() const { return QuestFlags; }
bool IsDaily() const { return QuestFlags & QUEST_FLAGS_DAILY; }
// multiple values
std::string ObjectiveText[QUEST_OBJECTIVES_COUNT];
uint32 ReqItemId[QUEST_OBJECTIVES_COUNT];
uint32 ReqItemCount[QUEST_OBJECTIVES_COUNT];
uint32 ReqSourceId[QUEST_SOURCE_ITEM_IDS_COUNT];
uint32 ReqSourceCount[QUEST_SOURCE_ITEM_IDS_COUNT];
uint32 ReqSourceRef[QUEST_SOURCE_ITEM_IDS_COUNT];
int32 ReqCreatureOrGOId[QUEST_OBJECTIVES_COUNT]; // >0 Creature <0 Gameobject
uint32 ReqCreatureOrGOCount[QUEST_OBJECTIVES_COUNT];
uint32 ReqSpell[QUEST_OBJECTIVES_COUNT];
uint32 RewChoiceItemId[QUEST_REWARD_CHOICES_COUNT];
uint32 RewChoiceItemCount[QUEST_REWARD_CHOICES_COUNT];
uint32 RewItemId[QUEST_REWARDS_COUNT];
uint32 RewItemCount[QUEST_REWARDS_COUNT];
uint32 RewRepFaction[QUEST_REPUTATIONS_COUNT];
int32 RewRepValue[QUEST_REPUTATIONS_COUNT];
uint32 DetailsEmote[QUEST_EMOTE_COUNT];
uint32 OfferRewardEmote[QUEST_EMOTE_COUNT];
uint32 GetReqItemsCount() const { return m_reqitemscount; }
uint32 GetReqCreatureOrGOcount() const { return m_reqCreatureOrGOcount; }
uint32 GetRewChoiceItemsCount() const { return m_rewchoiceitemscount; }
uint32 GetRewItemsCount() const { return m_rewitemscount; }
typedef std::vector<int32> PrevQuests;
PrevQuests prevQuests;
typedef std::vector<uint32> PrevChainQuests;
PrevChainQuests prevChainQuests;
// cached data
private:
uint32 m_reqitemscount;
uint32 m_reqCreatureOrGOcount;
uint32 m_rewchoiceitemscount;
uint32 m_rewitemscount;
// table data
protected:
uint32 QuestId;
uint32 QuestMethod;
int32 ZoneOrSort;
int32 SkillOrClass;
uint32 MinLevel;
uint32 QuestLevel;
uint32 Type;
uint32 RequiredRaces;
uint32 RequiredSkillValue;
uint32 RepObjectiveFaction;
int32 RepObjectiveValue;
uint32 RequiredMinRepFaction;
int32 RequiredMinRepValue;
uint32 RequiredMaxRepFaction;
int32 RequiredMaxRepValue;
uint32 SuggestedPlayers;
uint32 LimitTime;
uint32 QuestFlags;
uint32 CharTitleId;
int32 PrevQuestId;
int32 NextQuestId;
int32 ExclusiveGroup;
uint32 NextQuestInChain;
uint32 SrcItemId;
uint32 SrcItemCount;
uint32 SrcSpell;
std::string Title;
std::string Details;
std::string Objectives;
std::string OfferRewardText;
std::string RequestItemsText;
std::string EndText;
int32 RewOrReqMoney;
uint32 RewMoneyMaxLevel;
uint32 RewSpell;
uint32 RewSpellCast;
uint32 RewMailTemplateId;
uint32 RewMailDelaySecs;
uint32 PointMapId;
float PointX;
float PointY;
uint32 PointOpt;
uint32 IncompleteEmote;
uint32 CompleteEmote;
uint32 QuestStartScript;
uint32 QuestCompleteScript;
};
enum QuestUpdateState
{
QUEST_UNCHANGED = 0,
QUEST_CHANGED = 1,
QUEST_NEW = 2
};
struct QuestStatusData
{
QuestStatusData()
: m_status(QUEST_STATUS_NONE),m_rewarded(false),
m_explored(false), m_timer(0), uState(QUEST_NEW)
{
memset(m_itemcount, 0, QUEST_OBJECTIVES_COUNT * sizeof(uint32));
memset(m_creatureOrGOcount, 0, QUEST_OBJECTIVES_COUNT * sizeof(uint32));
}
QuestStatus m_status;
bool m_rewarded;
bool m_explored;
uint32 m_timer;
QuestUpdateState uState;
uint32 m_itemcount[ QUEST_OBJECTIVES_COUNT ];
uint32 m_creatureOrGOcount[ QUEST_OBJECTIVES_COUNT ];
};
#endif
+163 -159
View File
@@ -1,159 +1,163 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Creature.h"
#include "MapManager.h"
#include "RandomMovementGenerator.h"
#include "DestinationHolderImp.h"
#include "Map.h"
#include "Util.h"
#define RUNNING_CHANCE_RANDOMMV 20 //will be "1 / RUNNING_CHANCE_RANDOMMV"
template<>
void
RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature)
{
float X,Y,Z,z,nx,ny,nz,wander_distance,ori,dist;
creature.GetRespawnCoord(X, Y, Z);
creature.GetRespawnCoord(X, Y, Z, &ori, &wander_distance);
z = creature.GetPositionZ();
uint32 mapid=creature.GetMapId();
Map const* map = MapManager::Instance().GetBaseMap(mapid);
// For 2D/3D system selection
bool is_land_ok = creature.canWalk();
bool is_water_ok = creature.canSwim();
bool is_air_ok = creature.canFly();
const float angle = rand_norm()*(M_PI*2);
const float range = rand_norm()*wander_distance;
const float distanceX = range * cos(angle);
const float distanceY = range * sin(angle);
nx = X + distanceX;
ny = Y + distanceY;
dist = distanceX*distanceX + distanceY*distanceY;
if (is_air_ok) // 3D system above ground and above water (flying mode)
{
const float distanceZ = rand_norm() * sqrtf(dist)/2; // Limit height change
nz = Z + distanceZ;
float tz = map->GetHeight(nx, ny, nz-2.0f, false); // Map check only, vmap needed here but need to alter vmaps checks for height.
float wz = map->GetWaterLevel(nx, ny);
if (tz >= nz || wz >= nz)
return; // Problem here, we must fly above the ground and water, not under. Let's try on next tick
}
//else if (is_water_ok) // 3D system under water and above ground (swimming mode)
else // 2D only
{
dist = dist>=100.0f ? 10.0f : sqrtf(dist); // 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE)
// The fastest way to get an accurate result 90% of the time.
// Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long.
nz = map->GetHeight(nx,ny,Z+dist-2.0f,false); // Map check
if (fabs(nz-Z)>dist)
{
nz = map->GetHeight(nx,ny,Z-2.0f,true); // Vmap Horizontal or above
if (fabs(nz-Z)>dist)
{
nz = map->GetHeight(nx,ny,Z+dist-2.0f,true); // Vmap Higher
if (fabs(nz-Z)>dist)
return; // let's forget this bad coords where a z cannot be find and retry at next tick
}
}
}
Traveller<Creature> traveller(creature);
creature.SetOrientation(creature.GetAngle(nx,ny));
i_destinationHolder.SetDestination(traveller, nx, ny, nz);
creature.addUnitState(UNIT_STAT_ROAMING);
if (is_air_ok)
{
i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
creature.SetUnitMovementFlags(MOVEMENTFLAG_FLYING2);
}
//else if (is_water_ok) // Swimming mode to be done with more than this check
else
{
i_nextMoveTime.Reset(urand(500+i_destinationHolder.GetTotalTravelTime(),5000+i_destinationHolder.GetTotalTravelTime()));
creature.SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE);
}
}
template<>
void
RandomMovementGenerator<Creature>::Initialize(Creature &creature)
{
if(!creature.isAlive())
return;
if (creature.canFly())
creature.SetUnitMovementFlags(MOVEMENTFLAG_FLYING2);
else
creature.SetUnitMovementFlags(irand(0,RUNNING_CHANCE_RANDOMMV) > 0 ? MOVEMENTFLAG_WALK_MODE : MOVEMENTFLAG_NONE );
_setRandomLocation(creature);
}
template<>
void
RandomMovementGenerator<Creature>::Reset(Creature &creature)
{
Initialize(creature);
}
template<>
bool
RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{
if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED))
{
i_nextMoveTime.Update(i_nextMoveTime.GetExpiry()); // Expire the timer
creature.clearUnitState(UNIT_STAT_ROAMING);
return true;
}
i_nextMoveTime.Update(diff);
if(i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly())
creature.clearUnitState(UNIT_STAT_ROAMING);
if(!i_destinationHolder.HasArrived() && creature.IsStopped())
creature.addUnitState(UNIT_STAT_ROAMING);
CreatureTraveller traveller(creature);
if( i_destinationHolder.UpdateTraveller(traveller, diff, false, true) )
{
if(i_nextMoveTime.Passed())
{
if (creature.canFly())
creature.SetUnitMovementFlags(MOVEMENTFLAG_FLYING2);
else
creature.SetUnitMovementFlags(irand(0,RUNNING_CHANCE_RANDOMMV) > 0 ? MOVEMENTFLAG_WALK_MODE : MOVEMENTFLAG_NONE);
_setRandomLocation(creature);
}
else if(creature.isPet() && creature.GetOwner() && creature.GetDistance(creature.GetOwner()) > PET_FOLLOW_DIST+2.5f)
{
creature.SetUnitMovementFlags(MOVEMENTFLAG_NONE);
_setRandomLocation(creature);
}
}
return true;
}
/*
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Creature.h"
#include "MapManager.h"
#include "RandomMovementGenerator.h"
#include "DestinationHolderImp.h"
#include "Map.h"
#include "Util.h"
#define RUNNING_CHANCE_RANDOMMV 20 //will be "1 / RUNNING_CHANCE_RANDOMMV"
template<>
void
RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature)
{
float X,Y,Z,z,nx,ny,nz,wander_distance,ori,dist;
creature.GetRespawnCoord(X, Y, Z, &ori, &wander_distance);
z = creature.GetPositionZ();
uint32 mapid=creature.GetMapId();
Map const* map = MapManager::Instance().GetBaseMap(mapid);
// For 2D/3D system selection
bool is_land_ok = creature.canWalk();
bool is_water_ok = creature.canSwim();
bool is_air_ok = creature.canFly();
const float angle = rand_norm()*(M_PI*2);
const float range = rand_norm()*wander_distance;
const float distanceX = range * cos(angle);
const float distanceY = range * sin(angle);
nx = X + distanceX;
ny = Y + distanceY;
// prevent invalid coordinates generation
MaNGOS::NormalizeMapCoord(nx);
MaNGOS::NormalizeMapCoord(ny);
dist = distanceX*distanceX + distanceY*distanceY;
if (is_air_ok) // 3D system above ground and above water (flying mode)
{
const float distanceZ = rand_norm() * sqrtf(dist)/2; // Limit height change
nz = Z + distanceZ;
float tz = map->GetHeight(nx, ny, nz-2.0f, false); // Map check only, vmap needed here but need to alter vmaps checks for height.
float wz = map->GetWaterLevel(nx, ny);
if (tz >= nz || wz >= nz)
return; // Problem here, we must fly above the ground and water, not under. Let's try on next tick
}
//else if (is_water_ok) // 3D system under water and above ground (swimming mode)
else // 2D only
{
dist = dist>=100.0f ? 10.0f : sqrtf(dist); // 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE)
// The fastest way to get an accurate result 90% of the time.
// Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long.
nz = map->GetHeight(nx,ny,Z+dist-2.0f,false); // Map check
if (fabs(nz-Z)>dist)
{
nz = map->GetHeight(nx,ny,Z-2.0f,true); // Vmap Horizontal or above
if (fabs(nz-Z)>dist)
{
nz = map->GetHeight(nx,ny,Z+dist-2.0f,true); // Vmap Higher
if (fabs(nz-Z)>dist)
return; // let's forget this bad coords where a z cannot be find and retry at next tick
}
}
}
Traveller<Creature> traveller(creature);
creature.SetOrientation(creature.GetAngle(nx,ny));
i_destinationHolder.SetDestination(traveller, nx, ny, nz);
creature.addUnitState(UNIT_STAT_ROAMING);
if (is_air_ok)
{
i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
creature.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
}
//else if (is_water_ok) // Swimming mode to be done with more than this check
else
{
i_nextMoveTime.Reset(urand(500+i_destinationHolder.GetTotalTravelTime(),5000+i_destinationHolder.GetTotalTravelTime()));
creature.SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE);
}
}
template<>
void
RandomMovementGenerator<Creature>::Initialize(Creature &creature)
{
if(!creature.isAlive())
return;
if (creature.canFly())
creature.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
else
creature.SetUnitMovementFlags(irand(0,RUNNING_CHANCE_RANDOMMV) > 0 ? MOVEMENTFLAG_WALK_MODE : MOVEMENTFLAG_NONE );
_setRandomLocation(creature);
}
template<>
void
RandomMovementGenerator<Creature>::Reset(Creature &creature)
{
Initialize(creature);
}
template<>
bool
RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{
if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED))
{
i_nextMoveTime.Update(i_nextMoveTime.GetExpiry()); // Expire the timer
creature.clearUnitState(UNIT_STAT_ROAMING);
return true;
}
i_nextMoveTime.Update(diff);
if(i_destinationHolder.HasArrived() && !creature.IsStopped() && !creature.canFly())
creature.clearUnitState(UNIT_STAT_ROAMING);
if(!i_destinationHolder.HasArrived() && creature.IsStopped())
creature.addUnitState(UNIT_STAT_ROAMING);
CreatureTraveller traveller(creature);
if( i_destinationHolder.UpdateTraveller(traveller, diff, false, true) )
{
if(i_nextMoveTime.Passed())
{
if (creature.canFly())
creature.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
else
creature.SetUnitMovementFlags(irand(0,RUNNING_CHANCE_RANDOMMV) > 0 ? MOVEMENTFLAG_WALK_MODE : MOVEMENTFLAG_NONE);
_setRandomLocation(creature);
}
else if(creature.isPet() && creature.GetOwner() && creature.GetDistance(creature.GetOwner()) > PET_FOLLOW_DIST+2.5f)
{
creature.SetUnitMovementFlags(MOVEMENTFLAG_NONE);
_setRandomLocation(creature);
}
}
return true;
}
+5
View File
@@ -3681,6 +3681,11 @@ uint8 Spell::CanCast(bool strict)
(!m_targets.getItemTarget() || !m_targets.getItemTarget()->GetProto()->LockID || m_targets.getItemTarget()->GetOwner() != m_caster ) )
return SPELL_FAILED_BAD_TARGETS;
// In BattleGround players can use only flags and banners
if( ((Player*)m_caster)->InBattleGround() &&
!((Player*)m_caster)->isAllowUseBattleGroundObject() )
return SPELL_FAILED_TRY_AGAIN;
// get the lock entry
LockEntry const *lockInfo = NULL;
if (GameObject* go=m_targets.getGOTarget())
+103 -14
View File
@@ -52,6 +52,8 @@
#include "Language.h"
#include "SocialMgr.h"
#include "Util.h"
#include "TemporarySummon.h"
pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
{
@@ -1006,10 +1008,78 @@ void Spell::EffectDummy(uint32 i)
m_caster->CastSpell(m_caster,42337,true,NULL);
return;
}
case 37573: //Temporal Phase Modulator
{
if(!unitTarget)
return;
TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
if(!tempSummon)
return;
uint32 health = tempSummon->GetHealth();
const uint32 entry_list[6] = {21821, 21820, 21817};
float x = tempSummon->GetPositionX();
float y = tempSummon->GetPositionY();
float z = tempSummon->GetPositionZ();
float o = tempSummon->GetOrientation();
tempSummon->UnSummon();
Creature* pCreature = m_caster->SummonCreature(entry_list[urand(0, 2)], x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
if (!pCreature)
return;
pCreature->SetHealth(health);
if(pCreature->AI())
pCreature->AI()->AttackStart(m_caster);
return;
}
case 34665: //Administer Antidote
{
if(!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
return;
if(!unitTarget)
return;
TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
if(!tempSummon)
return;
uint32 health = tempSummon->GetHealth();
float x = tempSummon->GetPositionX();
float y = tempSummon->GetPositionY();
float z = tempSummon->GetPositionZ();
float o = tempSummon->GetOrientation();
tempSummon->UnSummon();
Creature* pCreature = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
if (!pCreature)
return;
pCreature->SetHealth(health);
((Player*)m_caster)->KilledMonster(16992,pCreature->GetGUID());
if (pCreature->AI())
pCreature->AI()->AttackStart(m_caster);
return;
}
case 44997: // Converting Sentry
{
//Converted Sentry Credit
m_caster->CastSpell(m_caster, 45009, true);
return;
}
case 45030: // Impale Emissary
{
// Emissary of Hate Credit
m_caster->CastSpell(m_caster,45088,true);
m_caster->CastSpell(m_caster, 45088, true);
return;
}
case 50243: // Teach Language
@@ -1102,6 +1172,16 @@ void Spell::EffectDummy(uint32 i)
}
return;
}
case 32826:
{
if ( unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT )
{
//Polymorph Cast Visual Rank 1
const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820};
unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
}
return;
}
}
break;
case SPELLFAMILY_WARRIOR:
@@ -2760,27 +2840,26 @@ void Spell::EffectOpenLock(uint32 /*i*/)
if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK )
{
if(BattleGround *bg = player->GetBattleGround())// in battleground
//isAllowUseBattleGroundObject() already called in CanCast()
// in battleground check
if(BattleGround *bg = player->GetBattleGround())
{
if( !player->IsMounted() && // not mounted
!player->HasStealthAura() && // not stealthed
!player->HasInvisibilityAura() && // not invisible
player->isAlive() ) // live player
{
// check if it's correct bg
if(bg && bg->GetTypeID() == BATTLEGROUND_AB)
bg->EventPlayerClickedOnFlag(player, gameObjTarget);
return;
}
// check if it's correct bg
if(bg && bg->GetTypeID() == BATTLEGROUND_AB)
bg->EventPlayerClickedOnFlag(player, gameObjTarget);
return;
}
}
else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
{
//isAllowUseBattleGroundObject() already called in CanCast()
// in battleground check
if(BattleGround *bg = player->GetBattleGround())
{
if(bg->GetTypeID() == BATTLEGROUND_EY)
bg->EventPlayerClickedOnFlag(player, gameObjTarget);
return;
return;
}
}
lockId = gameObjTarget->GetLockId();
guid = gameObjTarget->GetGUID();
@@ -4751,6 +4830,16 @@ void Spell::EffectScriptEffect(uint32 effIndex)
unitTarget->CastSpell(unitTarget, spellId, true);
break;
}
//5,000 Gold
case 46642:
{
if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
((Player*)unitTarget)->ModifyMoney(50000000);
break;
}
}
if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN )
+211 -202
View File
@@ -1,202 +1,211 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ByteBuffer.h"
#include "TargetedMovementGenerator.h"
#include "Errors.h"
#include "Creature.h"
#include "MapManager.h"
#include "DestinationHolderImp.h"
#include "World.h"
#define SMALL_ALPHA 0.05f
#include <cmath>
/*
struct StackCleaner
{
Creature &i_creature;
StackCleaner(Creature &creature) : i_creature(creature) {}
void Done(void) { i_creature.StopMoving(); }
~StackCleaner()
{
i_creature->Clear();
}
};
*/
template<class T>
void
TargetedMovementGenerator<T>::_setTargetLocation(T &owner)
{
if( !i_target.isValid() || !&owner )
return;
if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED) )
return;
// prevent redundant micro-movement for pets, other followers.
if(i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset))
return;
float x, y, z;
if(!i_offset)
{
// to nearest contact position
i_target->GetContactPoint( &owner, x, y, z );
}
else
{
// to at i_offset distance from target and i_angle from target facing
i_target->GetClosePoint(x,y,z,owner.GetObjectSize(),i_offset,i_angle);
}
/*
We MUST not check the distance difference and avoid setting the new location for smaller distances.
By that we risk having far too many GetContactPoint() calls freezing the whole system.
In TargetedMovementGenerator<T>::Update() we check the distance to the target and at
some range we calculate a new position. The calculation takes some processor cycles due to vmaps.
If the distance to the target it too large to ignore,
but the distance to the new contact point is short enough to be ignored,
we will calculate a new contact point each update loop, but will never move to it.
The system will freeze.
ralf
//We don't update Mob Movement, if the difference between New destination and last destination is < BothObjectSize
float bothObjectSize = i_target->GetObjectSize() + owner.GetObjectSize() + CONTACT_DISTANCE;
if( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize )
return;
*/
Traveller<T> traveller(owner);
i_destinationHolder.SetDestination(traveller, x, y, z);
owner.addUnitState(UNIT_STAT_CHASE);
}
template<class T>
void
TargetedMovementGenerator<T>::Initialize(T &owner)
{
if(!&owner)
return;
owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
_setTargetLocation(owner);
}
template<class T>
void
TargetedMovementGenerator<T>::Finalize(T &owner)
{
owner.clearUnitState(UNIT_STAT_CHASE);
}
template<class T>
void
TargetedMovementGenerator<T>::Reset(T &owner)
{
Initialize(owner);
}
template<class T>
bool
TargetedMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
{
if(!i_target.isValid())
return false;
if( !&owner || !owner.isAlive())
return true;
if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_FLEEING | UNIT_STAT_DISTRACTED) )
return true;
// prevent movement while casting spells with cast time or channel time
if ( owner.IsNonMeleeSpellCasted(false, false, true))
{
if (!owner.IsStopped())
owner.StopMoving();
return true;
}
// prevent crash after creature killed pet
if (!owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.getVictim() != i_target.getTarget())
return true;
Traveller<T> traveller(owner);
if( !i_destinationHolder.HasDestination() )
_setTargetLocation(owner);
if( owner.IsStopped() && !i_destinationHolder.HasArrived() )
{
owner.addUnitState(UNIT_STAT_CHASE);
i_destinationHolder.StartTravel(traveller);
return true;
}
if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false))
{
// put targeted movement generators on a higher priority
if (owner.GetObjectSize())
i_destinationHolder.ResetUpdate(50);
float dist = i_target->GetObjectSize() + owner.GetObjectSize() + sWorld.getRate(RATE_TARGET_POS_RECALCULATION_RANGE);
//More distance let have better performance, less distance let have more sensitive reaction at target move.
// try to counter precision differences
if( i_destinationHolder.GetDistance2dFromDestSq(*i_target.getTarget()) >= dist * dist)
{
owner.SetInFront(i_target.getTarget()); // Set new Angle For Map::
_setTargetLocation(owner); //Calculate New Dest and Send data To Player
}
// Update the Angle of the target only for Map::, no need to send packet for player
else if ( !i_angle && !owner.HasInArc( 0.01f, i_target.getTarget() ) )
owner.SetInFront(i_target.getTarget());
if(( owner.IsStopped() && !i_destinationHolder.HasArrived() ) || i_recalculateTravel )
{
i_recalculateTravel = false;
//Angle update will take place into owner.StopMoving()
owner.SetInFront(i_target.getTarget());
owner.StopMoving();
if(owner.canReachWithAttack(i_target.getTarget()) && !owner.hasUnitState(UNIT_STAT_FOLLOW))
owner.Attack(i_target.getTarget(),true);
}
}
return true;
}
template<class T>
Unit*
TargetedMovementGenerator<T>::GetTarget() const
{
return i_target.getTarget();
}
template void TargetedMovementGenerator<Player>::_setTargetLocation(Player &);
template void TargetedMovementGenerator<Creature>::_setTargetLocation(Creature &);
template void TargetedMovementGenerator<Player>::Initialize(Player &);
template void TargetedMovementGenerator<Creature>::Initialize(Creature &);
template void TargetedMovementGenerator<Player>::Finalize(Player &);
template void TargetedMovementGenerator<Creature>::Finalize(Creature &);
template void TargetedMovementGenerator<Player>::Reset(Player &);
template void TargetedMovementGenerator<Creature>::Reset(Creature &);
template bool TargetedMovementGenerator<Player>::Update(Player &, const uint32 &);
template bool TargetedMovementGenerator<Creature>::Update(Creature &, const uint32 &);
template Unit* TargetedMovementGenerator<Player>::GetTarget() const;
template Unit* TargetedMovementGenerator<Creature>::GetTarget() const;
/*
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ByteBuffer.h"
#include "TargetedMovementGenerator.h"
#include "Errors.h"
#include "Creature.h"
#include "MapManager.h"
#include "DestinationHolderImp.h"
#include "World.h"
#define SMALL_ALPHA 0.05f
#include <cmath>
/*
struct StackCleaner
{
Creature &i_creature;
StackCleaner(Creature &creature) : i_creature(creature) {}
void Done(void) { i_creature.StopMoving(); }
~StackCleaner()
{
i_creature->Clear();
}
};
*/
template<class T>
void
TargetedMovementGenerator<T>::_setTargetLocation(T &owner)
{
if( !i_target.isValid() || !&owner )
return;
if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_DISTRACTED) )
return;
// prevent redundant micro-movement for pets, other followers.
if(i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset))
return;
float x, y, z;
if(!i_offset)
{
// to nearest contact position
i_target->GetContactPoint( &owner, x, y, z );
}
else
{
// to at i_offset distance from target and i_angle from target facing
i_target->GetClosePoint(x,y,z,owner.GetObjectSize(),i_offset,i_angle);
}
/*
We MUST not check the distance difference and avoid setting the new location for smaller distances.
By that we risk having far too many GetContactPoint() calls freezing the whole system.
In TargetedMovementGenerator<T>::Update() we check the distance to the target and at
some range we calculate a new position. The calculation takes some processor cycles due to vmaps.
If the distance to the target it too large to ignore,
but the distance to the new contact point is short enough to be ignored,
we will calculate a new contact point each update loop, but will never move to it.
The system will freeze.
ralf
//We don't update Mob Movement, if the difference between New destination and last destination is < BothObjectSize
float bothObjectSize = i_target->GetObjectSize() + owner.GetObjectSize() + CONTACT_DISTANCE;
if( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize )
return;
*/
Traveller<T> traveller(owner);
i_destinationHolder.SetDestination(traveller, x, y, z);
owner.addUnitState(UNIT_STAT_CHASE);
if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly())
owner.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
}
template<class T>
void
TargetedMovementGenerator<T>::Initialize(T &owner)
{
if(!&owner)
return;
owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly())
owner.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
_setTargetLocation(owner);
}
template<class T>
void
TargetedMovementGenerator<T>::Finalize(T &owner)
{
owner.clearUnitState(UNIT_STAT_CHASE);
}
template<class T>
void
TargetedMovementGenerator<T>::Reset(T &owner)
{
Initialize(owner);
}
template<class T>
bool
TargetedMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
{
if(!i_target.isValid())
return false;
if( !&owner || !owner.isAlive())
return true;
if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED | UNIT_STAT_FLEEING | UNIT_STAT_DISTRACTED) )
return true;
// prevent movement while casting spells with cast time or channel time
if ( owner.IsNonMeleeSpellCasted(false, false, true))
{
if (!owner.IsStopped())
owner.StopMoving();
return true;
}
// prevent crash after creature killed pet
if (!owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.getVictim() != i_target.getTarget())
return true;
Traveller<T> traveller(owner);
if( !i_destinationHolder.HasDestination() )
_setTargetLocation(owner);
if( owner.IsStopped() && !i_destinationHolder.HasArrived() )
{
owner.addUnitState(UNIT_STAT_CHASE);
if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly())
owner.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
i_destinationHolder.StartTravel(traveller);
return true;
}
if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false))
{
// put targeted movement generators on a higher priority
if (owner.GetObjectSize())
i_destinationHolder.ResetUpdate(50);
float dist = i_target->GetObjectSize() + owner.GetObjectSize() + sWorld.getRate(RATE_TARGET_POS_RECALCULATION_RANGE);
//More distance let have better performance, less distance let have more sensitive reaction at target move.
// try to counter precision differences
if( i_destinationHolder.GetDistance2dFromDestSq(*i_target.getTarget()) >= dist * dist)
{
owner.SetInFront(i_target.getTarget()); // Set new Angle For Map::
_setTargetLocation(owner); //Calculate New Dest and Send data To Player
}
// Update the Angle of the target only for Map::, no need to send packet for player
else if ( !i_angle && !owner.HasInArc( 0.01f, i_target.getTarget() ) )
owner.SetInFront(i_target.getTarget());
if(( owner.IsStopped() && !i_destinationHolder.HasArrived() ) || i_recalculateTravel )
{
i_recalculateTravel = false;
//Angle update will take place into owner.StopMoving()
owner.SetInFront(i_target.getTarget());
owner.StopMoving();
if(owner.canReachWithAttack(i_target.getTarget()) && !owner.hasUnitState(UNIT_STAT_FOLLOW))
owner.Attack(i_target.getTarget(),true);
}
}
return true;
}
template<class T>
Unit*
TargetedMovementGenerator<T>::GetTarget() const
{
return i_target.getTarget();
}
template void TargetedMovementGenerator<Player>::_setTargetLocation(Player &);
template void TargetedMovementGenerator<Creature>::_setTargetLocation(Creature &);
template void TargetedMovementGenerator<Player>::Initialize(Player &);
template void TargetedMovementGenerator<Creature>::Initialize(Creature &);
template void TargetedMovementGenerator<Player>::Finalize(Player &);
template void TargetedMovementGenerator<Creature>::Finalize(Creature &);
template void TargetedMovementGenerator<Player>::Reset(Player &);
template void TargetedMovementGenerator<Creature>::Reset(Creature &);
template bool TargetedMovementGenerator<Player>::Update(Player &, const uint32 &);
template bool TargetedMovementGenerator<Creature>::Update(Creature &, const uint32 &);
template Unit* TargetedMovementGenerator<Player>::GetTarget() const;
template Unit* TargetedMovementGenerator<Creature>::GetTarget() const;
+2 -2
View File
@@ -112,7 +112,7 @@ WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &di
// Now we re-set destination to same node and start travel
creature.addUnitState(UNIT_STAT_ROAMING);
if (creature.canFly())
creature.SetUnitMovementFlags(MOVEMENTFLAG_FLYING2);
creature.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
const WaypointNode &node = i_path->at(i_currentNode);
i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
@@ -176,7 +176,7 @@ WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &di
{
creature.addUnitState(UNIT_STAT_ROAMING);
if (creature.canFly())
creature.SetUnitMovementFlags(MOVEMENTFLAG_FLYING2);
creature.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
const WaypointNode &node = i_path->at(i_currentNode);
i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
+4 -4
View File
@@ -52,8 +52,8 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_SYS_DEFAULT
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,2,6721,676
PRODUCTVERSION 0,2,6721,676
FILEVERSION 0,3,6731,680
PRODUCTVERSION 0,3,6731,680
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -69,12 +69,12 @@ BEGIN
BLOCK "080004b0"
BEGIN
VALUE "FileDescription", "TrinityCore"
VALUE "FileVersion", "0, 2, 6721, 676"
VALUE "FileVersion", "0, 3, 6731, 680"
VALUE "InternalName", "TrinityCore"
VALUE "LegalCopyright", "Copyright (C) 2008"
VALUE "OriginalFilename", "TrinityCore.exe"
VALUE "ProductName", "TrinityCore"
VALUE "ProductVersion", "0, 2, 6721, 676"
VALUE "ProductVersion", "0, 3, 6731, 680"
END
END
BLOCK "VarFileInfo"
+4 -4
View File
@@ -52,8 +52,8 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_SYS_DEFAULT
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,2,6721,676
PRODUCTVERSION 0,2,6721,676
FILEVERSION 0,3,6731,680
PRODUCTVERSION 0,3,6731,680
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -69,12 +69,12 @@ BEGIN
BLOCK "080004b0"
BEGIN
VALUE "FileDescription", "TrinityRealm"
VALUE "FileVersion", "0, 2, 6721, 676"
VALUE "FileVersion", "0, 3, 6731, 680"
VALUE "InternalName", "TrinityRealm"
VALUE "LegalCopyright", "Copyright (C) 2008"
VALUE "OriginalFilename", "TrinityRealm.exe"
VALUE "ProductName", "TrinityRealm"
VALUE "ProductVersion", "0, 2, 6721, 676"
VALUE "ProductVersion", "0, 3, 6731, 680"
END
END
BLOCK "VarFileInfo"
+10 -10
View File
@@ -49,7 +49,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/MP /wd 4748"
AdditionalOptions="/MP /wd 4748 /wd 4244"
Optimization="0"
AdditionalIncludeDirectories="..\..\dep\ACE_wrappers"
PreprocessorDefinitions="ACE_BUILD_DLL;_DEBUG;WIN32;_WINDOWS;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
@@ -138,7 +138,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/MP /wd 4748"
AdditionalOptions="/MP /wd 4748 /wd 4244"
Optimization="0"
AdditionalIncludeDirectories="..\..\dep\ACE_wrappers"
PreprocessorDefinitions="ACE_BUILD_DLL;_DEBUG;WIN32;_WINDOWS;_CRT_NONSTDC_NO_WARNINGS;_AMD64_;_WIN64;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
@@ -228,7 +228,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/MP /wd 4748"
AdditionalOptions="/MP /wd 4748 /wd 4244"
Optimization="2"
AdditionalIncludeDirectories="..\..\dep\ACE_wrappers"
PreprocessorDefinitions="ACE_BUILD_DLL;NDEBUG;WIN32;_WINDOWS;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
@@ -316,7 +316,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/MP /wd 4748"
AdditionalOptions="/MP /wd 4748 /wd 4244"
Optimization="2"
AdditionalIncludeDirectories="..\..\dep\ACE_wrappers"
PreprocessorDefinitions="ACE_BUILD_DLL;NDEBUG;WIN32;_WINDOWS;_CRT_NONSTDC_NO_WARNINGS;_AMD64_;_WIN64;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
@@ -2853,11 +2853,11 @@
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\OS_Errno.h"
RelativePath="..\..\dep\ACE_wrappers\ace\os_include\os_errno.h"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\os_include\os_errno.h"
RelativePath="..\..\dep\ACE_wrappers\ace\OS_Errno.h"
>
</File>
<File
@@ -3237,11 +3237,11 @@
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\OS_String.h"
RelativePath="..\..\dep\ACE_wrappers\ace\os_include\os_string.h"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\os_include\os_string.h"
RelativePath="..\..\dep\ACE_wrappers\ace\OS_String.h"
>
</File>
<File
@@ -3285,11 +3285,11 @@
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\os_include\sys\os_time.h"
RelativePath="..\..\dep\ACE_wrappers\ace\os_include\os_time.h"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\os_include\os_time.h"
RelativePath="..\..\dep\ACE_wrappers\ace\os_include\sys\os_time.h"
>
</File>
<File