/*
* Ascent MMORPG Server
* Copyright (C) 2005-2007 Ascent Team
*
* 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 3 of the License, or
* 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, see .
*
*/
#ifndef WOWSERVER_CREATURE_H
#define WOWSERVER_CREATURE_H
class CreatureTemplate;
#define MAX_CREATURE_ITEMS 128
#define MAX_CREATURE_LOOT 8
#define MAX_PET_SPELL 4
#include "Map.h"
struct CreatureItem
{
uint32 itemid;
int amount;
};
struct CreatureInfo
{
uint32 Id;
char * Name;
char * SubName;
uint32 Flags1;
uint32 Type;
uint32 Family;
uint32 Rank;
uint32 Unknown1;
uint32 SpellDataID;
uint32 DisplayID;
float unk2;
float unk3;
uint8 Civilian;
uint8 Leader;
std::string lowercase_name;
};
struct CreatureProto
{
uint32 Id;
uint32 MinLevel;
uint32 MaxLevel;
uint32 Faction;
uint32 MinHealth;
uint32 MaxHealth;
uint32 Mana;
float Scale;
uint32 NPCFLags;
uint32 AttackTime;
float MinDamage;
float MaxDamage;
uint32 RangedAttackTime;
float RangedMinDamage;
float RangedMaxDamage;
uint32 MountedDisplayID;
uint32 Item1SlotDisplay;
uint32 Item1Info1;
uint32 Item1Info2;
uint32 Item2SlotDisplay;
uint32 Item2Info1;
uint32 Item2Info2;
uint32 Item3SlotDisplay;
uint32 Item3Info1;
uint32 Item3Info2;
uint32 RespawnTime;
uint32 Resistances[7];
float CombatReach;
float BoundingRadius;
char * aura_string;
uint32 boss;
uint32 money;
uint32 invisibility_type;
uint32 death_state;
/* AI Stuff */
bool m_canRangedAttack;
bool m_canFlee;
float m_fleeHealth;
uint32 m_fleeDuration;
bool m_canCallForHelp;
float m_callForHelpHealth;
set start_auras;
list spells;
};
struct Formation{
uint32 fol;
float ang;
float dist;
};
enum UNIT_TYPE
{
NOUNITTYPE = 0,
BEAST = 1,
DRAGONSKIN = 2,
DEMON = 3,
ELEMENTAL = 4,
GIANT = 5,
UNDEAD = 6,
HUMANOID = 7,
CRITTER = 8,
MECHANICAL = 9,
UNIT_TYPE_MISC = 10,
};
enum FAMILY
{
FAMILY_WOLF = 1,
FAMILY_CAT,
FAMILY_SPIDER,
FAMILY_BEAR,
FAMILY_BOAR,
FAMILY_CROCILISK,
FAMILY_CARRION_BIRD,
FAMILY_CRAB,
FAMILY_GORILLA,
FAMILY_RAPTOR = 11,
FAMILY_TALLSTRIDER ,
FAMILY_FELHUNTER = 15,
FAMILY_VOIDWALKER,
FAMILY_SUCCUBUS,
FAMILY_DOOMGUARD = 19,
FAMILY_SCORPID,
FAMILY_TURTLE,
FAMILY_IMP = 23,
FAMILY_BAT,
FAMILY_HYENA,
FAMILY_OWL,
FAMILY_WIND_SERPENT,
FAMILY_REMOTE_CONTROL,
FAMILY_FELGUARD,
FAMILY_DRAGONHAWK,
FAMILY_RAVAGER,
FAMILY_WARP_STALKER,
FAMILY_SPOREBAT,
FAMILY_NETHER_RAY,
FAMILY_SERPENT
};
enum ELITE
{
ELITE_NORMAL = 0,
ELITE_ELITE,
ELITE_RAREELITE,
ELITE_WORLDBOSS,
ELITE_RARE
};
struct PetSpellCooldown
{
uint32 spellId;
int32 cooldown;
};
class CreatureAIScript;
class GossipScript;
class AuctionHouse;
struct Trainer;
#define CALL_SCRIPT_EVENT(obj, func) if(obj->GetTypeId() == TYPEID_UNIT && static_cast(obj)->GetScript() != NULL) static_cast(obj)->GetScript()->func
///////////////////
/// Creature object
class SERVER_DECL Creature : public Unit
{
public:
Creature(uint32 high, uint32 low);
virtual ~Creature();
bool Load(CreatureSpawn *spawn, uint32 mode, MapInfo *info);
void Load(CreatureProto * proto_, float x, float y, float z);
void AddToWorld();
void RemoveFromWorld(bool addrespawnevent);
/// Creation
void Create ( const char* creature_name, uint32 mapid, float x, float y, float z, float ang);
void CreateWayPoint ( uint32 WayPointID, uint32 mapid, float x, float y, float z, float ang);
/// Updates
virtual void Update( uint32 time );
/// Creature inventory
inline uint32 GetItemIdBySlot(uint32 slot) { return m_SellItems->at(slot).itemid; }
inline uint32 GetItemAmountBySlot(uint32 slot) { return m_SellItems->at(slot).amount; }
inline bool HasItems() { return ((m_SellItems != NULL) ? true : false); }
int32 GetSlotByItemId(uint32 itemid)
{
uint32 slot = 0;
for(std::vector::iterator itr = m_SellItems->begin(); itr != m_SellItems->end(); ++itr)
{
if(itr->itemid == itemid)
return slot;
else
++slot;
}
return -1;
}
uint32 GetItemAmountByItemId(uint32 itemid)
{
for(std::vector::iterator itr = m_SellItems->begin(); itr != m_SellItems->end(); ++itr)
{
if(itr->itemid == itemid)
return ((itr->amount < 1) ? 1 : itr->amount);
}
return 0;
}
inline void GetSellItemBySlot(uint32 slot, CreatureItem &ci)
{
ci = m_SellItems->at(slot);
}
void GetSellItemByItemId(uint32 itemid, CreatureItem &ci)
{
for(std::vector::iterator itr = m_SellItems->begin(); itr != m_SellItems->end(); ++itr)
{
if(itr->itemid == itemid)
{
ci = (*itr);
return;
}
}
ci.amount = 0;
ci.itemid = 0;
}
inline std::vector::iterator GetSellItemBegin() { return m_SellItems->begin(); }
inline std::vector::iterator GetSellItemEnd() { return m_SellItems->end(); }
inline uint32 GetSellItemCount() { return m_SellItems->size(); }
void RemoveVendorItem(uint32 itemid)
{
for(std::vector::iterator itr = m_SellItems->begin(); itr != m_SellItems->end(); ++itr)
{
if(itr->itemid == itemid)
{
m_SellItems->erase(itr);
return;
}
}
}
void AddVendorItem(uint32 itemid, uint32 amount);
/// Quests
void _LoadQuests();
bool HasQuests() { return m_quests != NULL; };
bool HasQuest(uint32 id, uint32 type)
{
if(!m_quests) return false;
for(std::list::iterator itr = m_quests->begin(); itr != m_quests->end(); ++itr)
{
if((*itr)->qst->id == id && (*itr)->type & type)
return true;
}
return false;
}
void AddQuest(QuestRelation *Q);
void DeleteQuest(QuestRelation *Q);
Quest *FindQuest(uint32 quest_id, uint8 quest_relation);
uint16 GetQuestRelation(uint32 quest_id);
uint32 NumOfQuests();
list::iterator QuestsBegin() { return m_quests->begin(); };
list::iterator QuestsEnd() { return m_quests->end(); };
void SetQuestList(std::list* qst_lst) { m_quests = qst_lst; };
inline bool isQuestGiver() { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER ); };
int32 FlatResistanceMod[7];
int32 BaseResistanceModPct[7];
int32 ResistanceModPct[7];
int32 FlatStatMod[5];
int32 StatModPct[5];
int32 TotalStatModPct[5];
int32 ModDamageDone[7];
float ModDamageDonePct[7];
void CalcResistance(uint32 type);
void CalcStat(uint32 type);
void RegenerateHealth();
void RegenerateMana();
inline bool CanSee(Unit* obj)
{
if(!obj)
return false;
if(!obj->m_stealth)
return true;
float steathlevel = (float)obj->GetStealthLevel();
if(steathlevel == 0.0f) steathlevel = 1.0f;
float visibility = (float)GetStealthDetect()/steathlevel;
float invisRange = visibility * 3 + GetFloatValue (UNIT_FIELD_BOUNDINGRADIUS) +obj->GetFloatValue (UNIT_FIELD_BOUNDINGRADIUS);
if (GetDistance2dSq (obj) <= invisRange * invisRange)
return true;
else
return false;
}
//Make this unit face another unit
bool setInFront(Unit* target);
/// Looting
void generateLoot();
bool Skinned;
bool Tagged;
uint64 TaggerGuid;
/// Misc
inline void setEmoteState(uint8 emote) { m_emoteState = emote; };
inline uint32 GetSQL_id() { return spawnid; };
virtual void setDeathState(DeathState s);
uint32 GetOldEmote() { return m_oldEmote; }
// Serialization
void SaveToDB();
void SaveToFile(std::stringstream & name);
//bool LoadFromDB(uint32 guid);
//bool LoadFromDB(CreatureTemplate *t);
void LoadAIAgents(CreatureTemplate * t);
void LoadAIAgents();
void DeleteFromDB();
void OnJustDied();
void OnRemoveCorpse();
void OnRespawn(MapMgr * m);
void SafeDelete();
//void Despawn();
void SummonExpire(); // this is used for guardians. They are non respawnable creatures linked to a player
// In Range
void AddInRangeObject(Object* pObj);
void OnRemoveInRangeObject(Object* pObj);
void ClearInRangeSet();
// Demon
void EnslaveExpire();
// Pet
void UpdatePet();
uint32 GetEnslaveCount() { return m_enslaveCount; }
void SetEnslaveCount(uint32 count) { m_enslaveCount = count; }
uint32 GetEnslaveSpell() { return m_enslaveSpell; }
void SetEnslaveSpell(uint32 spellId) { m_enslaveSpell = spellId; }
bool RemoveEnslave();
inline Player *GetTotemOwner() { return totemOwner; }
inline void SetTotemOwner(Player *owner) { totemOwner = owner; }
inline uint32 GetTotemSlot() { return totemSlot; }
inline void SetTotemSlot(uint32 slot) { totemSlot = slot; }
inline bool IsPickPocketed() { return m_PickPocketed; }
inline void SetPickPocketed(bool val = true) { m_PickPocketed = val; }
inline CreatureAIScript * GetScript() { return _myScriptClass; }
void LoadScript();
void CallScriptUpdate();
uint32 m_TaxiNode;
CreatureInfo *creature_info;
inline CreatureInfo *GetCreatureName()
{
return creature_info;
}
inline void SetCreatureName(CreatureInfo *ci) { creature_info = ci; }
inline GossipScript* GetGossipScript() { return _gossipScript; }
inline void SetGossipScript(GossipScript* GS) { _gossipScript = GS; }
inline Trainer* GetTrainer() { return mTrainer; }
void RegenerateFocus();
CreatureFamilyEntry * myFamily;
inline bool IsTotem() { return totemOwner != 0 && totemSlot != -1; }
void TotemExpire();
void FormationLinkUp(uint32 SqlId);
bool haslinkupevent;
WayPoint * CreateWaypointStruct();
uint32 spawnid;
uint32 original_emotestate;
CreatureProto * proto;
CreatureSpawn * m_spawn;
void OnPushToWorld();
void Despawn(uint32 delay, uint32 respawntime);
void TriggerScriptEvent(void * func);
AuctionHouse * auctionHouse;
bool has_waypoint_text;
bool has_combat_text;
void DeleteMe();
bool CanAddToWorld();
WayPointMap * m_custom_waypoint_map;
Player * m_escorter;
void DestroyCustomWaypointMap();
bool IsInLimboState() { return m_limbostate; }
uint32 GetLineByFamily(CreatureFamilyEntry * family){return family->skilline ? family->skilline : 0;};
void RemoveLimboState(Unit * healer);
void SetGuardWaypoints();
bool m_corpseEvent;
MapCell * m_respawnCell;
protected:
CreatureAIScript *_myScriptClass;
bool m_limbostate;
GossipScript *_gossipScript;
Trainer* mTrainer;
void _LoadGoods();
void _LoadGoods(std::list* lst);
void _LoadMovement();
/// Vendor data
std::vector* m_SellItems;
/// Taxi data
uint32 mTaxiNode;
/// Quest data
std::list* m_quests;
/// Pet
uint32 m_enslaveCount;
uint32 m_enslaveSpell;
Player * totemOwner;
int32 totemSlot;
bool m_PickPocketed;
uint32 _fields[UNIT_END];
};
#endif