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

View File

@ -271,6 +271,7 @@ void PseuInstanceConf::ApplyFromVarSet(VarSet &v)
enablechatai=(bool)atoi(v.Get("ENABLECHATAI").c_str());
notifyping=(bool)atoi(v.Get("NOTIFYPING").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
{

View File

@ -47,6 +47,7 @@ class PseuInstanceConf
bool enablechatai;
bool notifyping;
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);
}
// use ONLY this function to target objects and notify the server about it.
// (server & client need to stay synced)
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);
WorldPacket packet;
packet << guid;
@ -86,5 +89,54 @@ void WorldSession::SendSetSelection(uint64 guid)
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; }
void SetSlot(uint8 nr) { _slot = nr; }
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; }
bool IsInBag() const { return _bag != NULL; }
protected:
uint8 _slot;
Bag *_bag; // not yet implemented
Bag *_bag;
};

View File

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

View File

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

View File

@ -22,9 +22,9 @@ void Player::Create(uint64 guid)
Object::Create(guid);
}
MyCharacter::MyCharacter()
MyCharacter::MyCharacter() : Player()
{
_castingSpell = false;
SetTarget(0);
}
void MyCharacter::SetActionButtons(WorldPacket &data)
@ -43,53 +43,20 @@ void MyCharacter::SetSpells(WorldPacket &data)
data >> spellid >> spellslot;
logdebug("Initial Spell: id=%u slot=%u",spellid,spellslot);
spell _spell;
_spell.spellId = spellid;
_spell.spellSlot = spellslot;
SpellBookEntry _spell;
_spell.id = spellid;
_spell.slot = spellslot;
_spells.push_back(_spell);
}
}
void MyCharacter::CastSpell(uint32 spellId, uint64 target)
uint16 MyCharacter::GetSpellSlot(uint32 spellid)
{
/*
if (_castingSpell)
return;
_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);
*/
for(std::vector<SpellBookEntry>::iterator i=_spells.begin(); i != _spells.end(); i++)
if(i->id == spellid)
return i->slot;
return 0;
}
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
{
public:
@ -197,19 +203,18 @@ public:
void SetActionButtons(WorldPacket &data);
void SetSpells(WorldPacket &data);
void CastSpell(uint32 spellId, uint64 target);
void HandleCastResultOpcode(WorldPacket &packet);
uint64 GetTarget(void) { return _target; }
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:
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,
};
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

View File

@ -24,10 +24,8 @@ WorldSession::WorldSession(PseuInstance *in)
_myGUID=0; // i dont have a guid yet
plrNameCache.ReadFromFile(); // load names/guids of known players
ItemProtoCache_InsertDataToSession(this);
myCharacter = new MyCharacter();
_deleteme = false;
_channels = new Channel(this);
// _playerSettings->Init(this);
//...
}
@ -366,13 +364,14 @@ void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket)
return;
} else {
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;
pkt.SetOpcode(CMSG_PLAYER_LOGIN);
pkt << _myGUID;
_targetGUID=0;
_followGUID=0;
SendWorldPacket(pkt);
}
}
@ -632,11 +631,23 @@ void WorldSession::_HandleChannelNotifyOpcode(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)
{
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 GetGuid(void) { return _myGUID; }
Channel *GetChannels(void) { return _channels; }
// Player *GetPlayer(void) { return _player; }
// PlayerSettings *GetPlayerSettings(void) { return _playerSettings; }
MyCharacter *GetMyChar(void) { ASSERT(_myGUID > 0); return (MyCharacter*)objmgr.GetObj(_myGUID); }
// CMSGConstructor
@ -61,9 +60,9 @@ public:
void SendEmote(uint32);
void SendQueryItem(uint32, uint64);
void SendSetSelection(uint64);
void SendCastSpell(uint32);
PlayerNameCache plrNameCache;
MyCharacter *myCharacter;
ObjMgr objmgr;
private: