* corrected MyCharacter & related

* implemented basic spellcasting, more to come.
* new conf option: "disablespellcheck"
* reactivated DefScript command "castspell"
* added selfheal.def for GMs
* misc stuff
This commit is contained in:
False.Genesis 2007-03-05 15:05:22 +00:00
parent 17e6692007
commit 242e9cafcd
12 changed files with 123 additions and 76 deletions

View File

@ -176,10 +176,7 @@ bool DefScriptPackage::SCcastspell(CmdSet Set)
return false; return false;
} }
uint32 spellId = 0;// = atoi(Set.defaultarg.c_str()); uint32 spellId = atoi(Set.defaultarg.c_str());
uint64 spellTarget = 0;// atoi(Set.arg[0]);
spellId = atoi(Set.defaultarg.c_str());
if (spellId <= 0) if (spellId <= 0)
{ {
@ -187,12 +184,7 @@ bool DefScriptPackage::SCcastspell(CmdSet Set)
return false; return false;
} }
if (spellTarget <= 0) ((PseuInstance*)parentMethod)->GetWSession()->SendCastSpell(spellId);
{
spellTarget = ((PseuInstance*)parentMethod)->GetWSession()->GetGuid();
}
// ((PseuInstance*)parentMethod)->GetWSession()->GetPlayerSettings()->CastSpell(spellId, spellTarget);
return true; return true;
} }

View File

@ -271,6 +271,7 @@ void PseuInstanceConf::ApplyFromVarSet(VarSet &v)
enablechatai=(bool)atoi(v.Get("ENABLECHATAI").c_str()); enablechatai=(bool)atoi(v.Get("ENABLECHATAI").c_str());
notifyping=(bool)atoi(v.Get("NOTIFYPING").c_str()); notifyping=(bool)atoi(v.Get("NOTIFYPING").c_str());
showmyopcodes=(bool)atoi(v.Get("SHOWMYOPCODES").c_str()); showmyopcodes=(bool)atoi(v.Get("SHOWMYOPCODES").c_str());
disablespellcheck=(bool)atoi(v.Get("DISABLESPELLCHECK").c_str());
// clientversion is a bit more complicated to add // clientversion is a bit more complicated to add
{ {

View File

@ -47,6 +47,7 @@ class PseuInstanceConf
bool enablechatai; bool enablechatai;
bool notifyping; bool notifyping;
bool showmyopcodes; bool showmyopcodes;
bool disablespellcheck;
}; };

View File

@ -76,9 +76,12 @@ void WorldSession::SendQueryItem(uint32 id, uint64 guid) // is it a guid? not su
SendWorldPacket(packet); SendWorldPacket(packet);
} }
// use ONLY this function to target objects and notify the server about it.
// (server & client need to stay synced)
void WorldSession::SendSetSelection(uint64 guid) void WorldSession::SendSetSelection(uint64 guid)
{ {
// TODO: MyCharacter.SetTarget(guid); ASSERT(GetMyChar()) // we need to be logged in to select something
GetMyChar()->SetTarget(guid);
logdebug("SetSelection GUID="I64FMT,guid); logdebug("SetSelection GUID="I64FMT,guid);
WorldPacket packet; WorldPacket packet;
packet << guid; packet << guid;
@ -86,5 +89,54 @@ void WorldSession::SendSetSelection(uint64 guid)
SendWorldPacket(packet); SendWorldPacket(packet);
} }
void WorldSession::SendCastSpell(uint32 spellid)
{
if(!spellid)
return;
MyCharacter *my = GetMyChar();
bool known = my->HasSpell(spellid);
if( (!known) && (!GetInstance()->GetConf()->disablespellcheck) )
{
logerror("Attempt to cast not-known spell %u",spellid);
return;
}
Object *target = objmgr.GetObj(my->GetTarget());
if(!target) // this is wrong, some spells dont require a target (areaspells, self-only spells)
return; // but for now, this should be ok, until a db is used that provides spell info
WorldPacket packet;
ByteBuffer temp;
uint16 flags=TARGET_FLAG_SELF; // target mask. spellcast implementeation needs to be changed if TARGET_MASK_SELF is != 0
packet << spellid;
if(my->GetTarget() != GetGuid()) // self cast?
{
if(target->GetTypeId() == TYPEID_PLAYER || target->GetTypeId() == TYPEID_UNIT)
{
flags |= TARGET_FLAG_UNIT;
temp << (uint8)0xFF << my->GetTarget(); // need to send packed guid?
}
if(target->GetTypeId() == TYPEID_OBJECT)
{
flags |= TARGET_FLAG_OBJECT;
temp << (uint8)0xFF <<my->GetTarget(); // need to send packed guid?
}
// TODO: need implementation of areaspells & item targets (enchant) here (temp << itemGUID)!
// TODO: append floats x,y,z according to target type srcloc & dstloc to temp
// TODO: append string to temp if TARGET_FLAG_STRING is set. what string for what purpose??
// and whats with TARGET_CORPSE?
}
packet << flags;
packet.append(temp);
// cast it
packet.SetOpcode(CMSG_CAST_SPELL);
SendWorldPacket(packet);
logdetail("Casting spell %u on target "I64FMT,spellid,my->GetTarget());
if(!known)
logerror(" - WARNING: spell is NOT known!");
}

View File

@ -398,13 +398,13 @@ public:
uint8 GetSlot(void) { return _slot; } uint8 GetSlot(void) { return _slot; }
void SetSlot(uint8 nr) { _slot = nr; } void SetSlot(uint8 nr) { _slot = nr; }
uint32 GetEntry() const { return GetUInt32Value(OBJECT_FIELD_ENTRY); } uint32 GetEntry() const { return GetUInt32Value(OBJECT_FIELD_ENTRY); }
uint32 GetCount() const { return GetUInt32Value (ITEM_FIELD_STACK_COUNT); } uint32 GetCount() const { return GetUInt32Value(ITEM_FIELD_STACK_COUNT); }
Bag *GetBag(void) { return _bag; } Bag *GetBag(void) { return _bag; }
bool IsInBag() const { return _bag != NULL; } bool IsInBag() const { return _bag != NULL; }
protected: protected:
uint8 _slot; uint8 _slot;
Bag *_bag; // not yet implemented Bag *_bag;
}; };

View File

@ -1,6 +1,11 @@
#include "ObjMgr.h" #include "ObjMgr.h"
ObjMgr::~ObjMgr() ObjMgr::~ObjMgr()
{
RemoveAll();
}
void ObjMgr::RemoveAll(void)
{ {
for(ItemProtoList::iterator i = _iproto.begin(); i!=_iproto.end(); i++) for(ItemProtoList::iterator i = _iproto.begin(); i!=_iproto.end(); i++)
{ {
@ -31,6 +36,8 @@ void ObjMgr::Add(Object *o)
Object *ObjMgr::GetObj(uint64 guid) Object *ObjMgr::GetObj(uint64 guid)
{ {
if(!guid)
return NULL;
for(ObjectList::iterator i = _obj.begin(); i!=_obj.end(); i++) for(ObjectList::iterator i = _obj.begin(); i!=_obj.end(); i++)
if((*i)->GetGUID() == guid) if((*i)->GetGUID() == guid)
return (*i); return (*i);

View File

@ -13,6 +13,7 @@ class ObjMgr
{ {
public: public:
~ObjMgr(); ~ObjMgr();
void RemoveAll(void); // TODO: this needs to be called on SMSG_LOGOUT_COMPLETE once implemented.
// Item Prototype functions // Item Prototype functions
uint32 GetItemProtoCount(void) { return _iproto.size(); } uint32 GetItemProtoCount(void) { return _iproto.size(); }

View File

@ -22,9 +22,9 @@ void Player::Create(uint64 guid)
Object::Create(guid); Object::Create(guid);
} }
MyCharacter::MyCharacter() MyCharacter::MyCharacter() : Player()
{ {
_castingSpell = false; SetTarget(0);
} }
void MyCharacter::SetActionButtons(WorldPacket &data) void MyCharacter::SetActionButtons(WorldPacket &data)
@ -43,53 +43,20 @@ void MyCharacter::SetSpells(WorldPacket &data)
data >> spellid >> spellslot; data >> spellid >> spellslot;
logdebug("Initial Spell: id=%u slot=%u",spellid,spellslot); logdebug("Initial Spell: id=%u slot=%u",spellid,spellslot);
spell _spell; SpellBookEntry _spell;
_spell.spellId = spellid; _spell.id = spellid;
_spell.spellSlot = spellslot; _spell.slot = spellslot;
_spells.push_back(_spell); _spells.push_back(_spell);
} }
} }
void MyCharacter::CastSpell(uint32 spellId, uint64 target) uint16 MyCharacter::GetSpellSlot(uint32 spellid)
{ {
/* for(std::vector<SpellBookEntry>::iterator i=_spells.begin(); i != _spells.end(); i++)
if (_castingSpell) if(i->id == spellid)
return; return i->slot;
return 0;
_castingSpell = !_castingSpell;
WorldPacket packet;
packet.SetOpcode(CMSG_CAST_SPELL);
packet << spellId << (uint16)2 << (uint8)1 << (uint8)target; // 2 = TARGET_FLAG_UNIT
// Can be bugged, not fully tested, probably doesn't work when the guid is high
// Damn packed guid stuff! xD
_worldSession->SendWorldPacket(packet);
*/
} }
void MyCharacter::HandleCastResultOpcode(WorldPacket &packet)
{
/*
uint32 spellId;
uint8 statusFail;
uint8 failProblem;
char l[150];
packet >> spellId >> statusFail;
_castingSpell = false;
sprintf(l, "Received cast result opcode. Spell = %d, statusFail = %d", spellId, statusFail);
if (statusFail == 2) // Spell cast failed
{
packet >> failProblem;
sprintf(l, "%s, failProblem = %d", l, failProblem);
}
//logdetail(l);
*/
}

View File

@ -175,6 +175,12 @@ private:
}; };
struct SpellBookEntry
{
uint32 id;
uint16 slot;
};
class Player : public Unit class Player : public Unit
{ {
public: public:
@ -197,19 +203,18 @@ public:
void SetActionButtons(WorldPacket &data); void SetActionButtons(WorldPacket &data);
void SetSpells(WorldPacket &data); void SetSpells(WorldPacket &data);
void CastSpell(uint32 spellId, uint64 target); uint64 GetTarget(void) { return _target; }
void HandleCastResultOpcode(WorldPacket &packet); void SetTarget(uint64 guid) { _target = guid; } // should only be called by WorldSession::SendSetSelection() !!
bool HasSpell(uint32 spellid) { return GetSpellSlot(spellid) != 0; }
uint16 GetSpellSlot(uint32 spellid);
private: private:
bool _castingSpell; // bool _castingSpell; // this is something we dont really need for now
typedef struct
{
uint16 spellId;
uint16 spellSlot;
} spell;
std::vector<spell> _spells;
std::vector<SpellBookEntry> _spells;
uint64 _target; // currently targeted object
}; };

View File

@ -988,4 +988,15 @@ enum ChatMsg
CHAT_MSG_LOOT = 0x18, CHAT_MSG_LOOT = 0x18,
}; };
enum SpellCastTargetFlags
{
TARGET_FLAG_SELF = 0x0000,
TARGET_FLAG_UNIT = 0x0002,
TARGET_FLAG_OBJECT = 0x0800,
TARGET_FLAG_ITEM = 0x1010,
TARGET_FLAG_SOURCE_LOCATION = 0x0020,
TARGET_FLAG_DEST_LOCATION = 0x0040,
TARGET_FLAG_STRING = 0x2000
};
#endif #endif

View File

@ -24,10 +24,8 @@ WorldSession::WorldSession(PseuInstance *in)
_myGUID=0; // i dont have a guid yet _myGUID=0; // i dont have a guid yet
plrNameCache.ReadFromFile(); // load names/guids of known players plrNameCache.ReadFromFile(); // load names/guids of known players
ItemProtoCache_InsertDataToSession(this); ItemProtoCache_InsertDataToSession(this);
myCharacter = new MyCharacter();
_deleteme = false; _deleteme = false;
_channels = new Channel(this); _channels = new Channel(this);
// _playerSettings->Init(this);
//... //...
} }
@ -366,13 +364,14 @@ void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket)
return; return;
} else { } else {
log("Entering World with Character \"%s\"...",GetInstance()->GetConf()->charname.c_str()); log("Entering World with Character \"%s\"...",GetInstance()->GetConf()->charname.c_str());
// _player->Init(plr[i]); // create the character and add it to the objmgr.
MyCharacter *my = new MyCharacter();
my->Create(_myGUID);
objmgr.Add(my);
WorldPacket pkt; WorldPacket pkt;
pkt.SetOpcode(CMSG_PLAYER_LOGIN); pkt.SetOpcode(CMSG_PLAYER_LOGIN);
pkt << _myGUID; pkt << _myGUID;
_targetGUID=0;
_followGUID=0;
SendWorldPacket(pkt); SendWorldPacket(pkt);
} }
} }
@ -632,11 +631,23 @@ void WorldSession::_HandleChannelNotifyOpcode(WorldPacket& recvPacket)
void WorldSession::_HandleCastResultOpcode(WorldPacket& recvPacket) void WorldSession::_HandleCastResultOpcode(WorldPacket& recvPacket)
{ {
// _playerSettings->HandleCastResultOpcode(recvPacket); uint32 spellid;
uint8 flag,result;
recvPacket >> spellid >> flag;
if(flag)
{
recvPacket >> result;
logdetail("Cast of spell %u failed. flag=%u, result=%u",spellid,flag,result);
}
else
{
logdetail("Cast of spell %u successful.",spellid);
}
} }
void WorldSession::_HandleInitialSpellsOpcode(WorldPacket& recvPacket) void WorldSession::_HandleInitialSpellsOpcode(WorldPacket& recvPacket)
{ {
myCharacter->SetSpells(recvPacket); // suggestion for later: what about MyCharacter->AddSpellBookEntry() ?
GetMyChar()->SetSpells(recvPacket);
} }

View File

@ -50,8 +50,7 @@ public:
uint64 GetFollowTarget(void) { return _followGUID; } uint64 GetFollowTarget(void) { return _followGUID; }
uint64 GetGuid(void) { return _myGUID; } uint64 GetGuid(void) { return _myGUID; }
Channel *GetChannels(void) { return _channels; } Channel *GetChannels(void) { return _channels; }
// Player *GetPlayer(void) { return _player; } MyCharacter *GetMyChar(void) { ASSERT(_myGUID > 0); return (MyCharacter*)objmgr.GetObj(_myGUID); }
// PlayerSettings *GetPlayerSettings(void) { return _playerSettings; }
// CMSGConstructor // CMSGConstructor
@ -61,9 +60,9 @@ public:
void SendEmote(uint32); void SendEmote(uint32);
void SendQueryItem(uint32, uint64); void SendQueryItem(uint32, uint64);
void SendSetSelection(uint64); void SendSetSelection(uint64);
void SendCastSpell(uint32);
PlayerNameCache plrNameCache; PlayerNameCache plrNameCache;
MyCharacter *myCharacter;
ObjMgr objmgr; ObjMgr objmgr;
private: private: