diff --git a/apps/openmw-mp/Script/Functions/Spells.cpp b/apps/openmw-mp/Script/Functions/Spells.cpp index 2375fe591..05fbf5011 100644 --- a/apps/openmw-mp/Script/Functions/Spells.cpp +++ b/apps/openmw-mp/Script/Functions/Spells.cpp @@ -49,6 +49,70 @@ void SpellFunctions::AddSpell(unsigned short pid, const char* spellId) noexcept player->spellbookChanges.spells.push_back(spell); } +void SpellFunctions::AddCustomSpell(unsigned short pid, const char* spellId, const char* spellName) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + ESM::Spell spell; + spell.mName = spellName; + spell.mId = spellId; + + player->spellbookChanges.spells.push_back(spell); +} + +void SpellFunctions::AddCustomSpellData(unsigned short pid, const char* spellId, int type, int cost, int flags) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + int index = -1; + for(int i = 0; i < player->spellbookChanges.spells.size(); i++) + { + if( strcmp(player->spellbookChanges.spells.at(i).mId.c_str(), spellId) == 0) + { + index = i; + } + } + + if(index == -1) + return; + + player->spellbookChanges.spells.at(index).mData.mType = type; + player->spellbookChanges.spells.at(index).mData.mCost = cost; + player->spellbookChanges.spells.at(index).mData.mFlags = flags; +} + +void SpellFunctions::AddCustomSpellEffect(unsigned short pid, const char* spellId, short effectId, signed char mSkill, signed char mAttribute, int mRange, int mArea, int mDuration, int mMagnMin, int mMagnMax) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + int index = -1; + for(int i = 0; i < player->spellbookChanges.spells.size(); i++) + { + if( strcmp(player->spellbookChanges.spells.at(i).mId.c_str(), spellId) == 0) + { + index = i; + } + } + + if(index == -1) + return; + + ESM::ENAMstruct effect; + effect.mEffectID = effectId; + effect.mSkill = mSkill; + effect.mAttribute = mAttribute; + effect.mRange = mRange; + effect.mArea = mArea; + effect.mDuration = mDuration; + effect.mMagnMin = mMagnMin; + effect.mMagnMax = mMagnMax; + + player->spellbookChanges.spells.at(index).mEffects.mList.push_back(effect); +} + const char *SpellFunctions::GetSpellId(unsigned short pid, unsigned int i) noexcept { Player *player; @@ -60,6 +124,149 @@ const char *SpellFunctions::GetSpellId(unsigned short pid, unsigned int i) noexc return player->spellbookChanges.spells.at(i).mId.c_str(); } +const char *SpellFunctions::GetSpellName(unsigned short pid, unsigned int i) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ""); + + if (i >= player->spellbookChanges.count) + return "invalid"; + + return player->spellbookChanges.spells.at(i).mName.c_str(); +} + +int SpellFunctions::GetSpellType(unsigned short pid, unsigned int i) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + if (i >= player->spellbookChanges.count) + return 0; + + return player->spellbookChanges.spells.at(i).mData.mType; +} + +int SpellFunctions::GetSpellCost(unsigned short pid, unsigned int i) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + if (i >= player->spellbookChanges.count) + return 0; + + return player->spellbookChanges.spells.at(i).mData.mCost; +} + +int SpellFunctions::GetSpellFlags(unsigned short pid, unsigned int i) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + if (i >= player->spellbookChanges.count) + return 0; + + return player->spellbookChanges.spells.at(i).mData.mFlags; +} + +unsigned int SpellFunctions::GetSpellEffectCount(unsigned short pid, unsigned int i) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + if (i >= player->spellbookChanges.count) + return 0; + + return player->spellbookChanges.spells.at(i).mEffects.mList.size(); +} + +short SpellFunctions::GetSpellEffectId(unsigned short pid, unsigned int i, unsigned int j) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + if (i >= player->spellbookChanges.count) + return 0; + + return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mEffectID; +} + +signed char SpellFunctions::GetSpellEffectSkill(unsigned short pid, unsigned int i, unsigned int j) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + if (i >= player->spellbookChanges.count) + return 0; + + return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mSkill; +} + +signed char SpellFunctions::GetSpellEffectAttribute(unsigned short pid, unsigned int i, unsigned int j) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + if (i >= player->spellbookChanges.count) + return 0; + + return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mAttribute; +} + +int SpellFunctions::GetSpellEffectRange(unsigned short pid, unsigned int i, unsigned int j) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + if (i >= player->spellbookChanges.count) + return 0; + + return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mRange; +} + +int SpellFunctions::GetSpellEffectArea(unsigned short pid, unsigned int i, unsigned int j) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + if (i >= player->spellbookChanges.count) + return 0; + + return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mArea; +} + +int SpellFunctions::GetSpellEffectDuration(unsigned short pid, unsigned int i, unsigned int j) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + if (i >= player->spellbookChanges.count) + return 0; + + return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mDuration; +} + +int SpellFunctions::GetSpellEffectMagnMin(unsigned short pid, unsigned int i, unsigned int j) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + if (i >= player->spellbookChanges.count) + return 0; + + return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mMagnMin; +} + +int SpellFunctions::GetSpellEffectMagnMax(unsigned short pid, unsigned int i, unsigned int j) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + if (i >= player->spellbookChanges.count) + return 0; + + return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mMagnMax; +} + void SpellFunctions::SendSpellbookChanges(unsigned short pid, bool toOthers) noexcept { Player *player; diff --git a/apps/openmw-mp/Script/Functions/Spells.hpp b/apps/openmw-mp/Script/Functions/Spells.hpp index bf3e1d307..6984a8455 100644 --- a/apps/openmw-mp/Script/Functions/Spells.hpp +++ b/apps/openmw-mp/Script/Functions/Spells.hpp @@ -9,8 +9,24 @@ \ {"SetSpellbookChangesAction", SpellFunctions::SetSpellbookChangesAction},\ {"AddSpell", SpellFunctions::AddSpell},\ + {"AddCustomSpell", SpellFunctions::AddCustomSpell},\ + {"AddCustomSpellData", SpellFunctions::AddCustomSpellData},\ + {"AddCustomSpellEffect", SpellFunctions::AddCustomSpellEffect},\ \ {"GetSpellId", SpellFunctions::GetSpellId},\ + {"GetSpellName", SpellFunctions::GetSpellName},\ + {"GetSpellType", SpellFunctions::GetSpellType},\ + {"GetSpellCost", SpellFunctions::GetSpellCost},\ + {"GetSpellFlags", SpellFunctions::GetSpellFlags},\ + {"GetSpellEffectCount", SpellFunctions::GetSpellEffectCount},\ + {"GetSpellEffectId", SpellFunctions::GetSpellEffectId},\ + {"GetSpellEffectSkill", SpellFunctions::GetSpellEffectSkill},\ + {"GetSpellEffectAttribute", SpellFunctions::GetSpellEffectAttribute},\ + {"GetSpellEffectRange", SpellFunctions::GetSpellEffectRange},\ + {"GetSpellEffectArea", SpellFunctions::GetSpellEffectArea},\ + {"GetSpellEffectDuration", SpellFunctions::GetSpellEffectDuration},\ + {"GetSpellEffectMagnMin", SpellFunctions::GetSpellEffectMagnMin},\ + {"GetSpellEffectMagnMax", SpellFunctions::GetSpellEffectMagnMax},\ \ {"SendSpellbookChanges", SpellFunctions::SendSpellbookChanges} @@ -57,11 +73,50 @@ public: * \brief Add a new spell to the spellbook changes for a player. * * \param pid The player ID whose spellbook changes should be used. - * \param topicId The spellId of the spell. + * \param spellId The spellId of the spell. * \return void */ static void AddSpell(unsigned short pid, const char* spellId) noexcept; + /** + * \brief Add a new custom spell to the spellbook changes for a player. + * + * \param pid The player ID whose spellbook changes should be used. + * \param spellId The spellId of the spell. + * \param spellName The name of the spell. + * \return void + */ + static void AddCustomSpell(unsigned short pid, const char* spellId, const char* spellName) noexcept; + + /** + * \brief Add custom spell data to the spellbook changes for a player. + * + * \param pid The player ID whose spellbook changes should be used. + * \param spellId The spellId of the spell. + * \param type The type of the spell. + * \param cost The cost of the spell. + * \param flags The flags of the spell. + * \return void + */ + static void AddCustomSpellData(unsigned short pid, const char* spellId, int type, int cost, int flags) noexcept; + + /** + * \brief Add custom spell effect to the spellbook changes for a player. + * + * \param pid The player ID whose spellbook changes should be used. + * \param spellId The spellId of the spell. + * \param effectId The effectId of the spell effect. + * \param mSkill The skill affected by the spell effect. + * \param mAttribute The attribute affected by the spell effect. + * \param mRange The range of the spell effect. + * \param mArea The area of the spell effect. + * \param mDuration The duration of the spell effect. + * \param mMagnMin The minimum magnitude of the spell effect. + * \param mMagnMax The maximum magnitude of the spell effect. + * \return void + */ + static void AddCustomSpellEffect(unsigned short pid, const char* spellId, short effectId, signed char mSkill, signed char mAttribute, int mRange, int mArea, int mDuration, int mMagnMin, int mMagnMax) noexcept; + /** * \brief Get the spellId at a certain index in a player's latest spellbook changes. * @@ -71,6 +126,131 @@ public: */ static const char *GetSpellId(unsigned short pid, unsigned int i) noexcept; + /** + * \brief Get the name of the spell at a certain index in a player's latest spellbook changes. + * + * \param pid The player ID whose spellbook changes should be used. + * \param i The index of the spell. + * \return The spell name. + */ + static const char *GetSpellName(unsigned short pid, unsigned int i) noexcept; + + /** + * \brief Get the type of the spell at a certain index in a player's latest spellbook changes. + * + * \param pid The player ID whose spellbook changes should be used. + * \param i The index of the spell. + * \return The spell type. + */ + static int GetSpellType(unsigned short pid, unsigned int i) noexcept; + + /** + * \brief Get the cost of the spell at a certain index in a player's latest spellbook changes. + * + * \param pid The player ID whose spellbook changes should be used. + * \param i The index of the spell. + * \return The spell cost. + */ + static int GetSpellCost(unsigned short pid, unsigned int i) noexcept; + + /** + * \brief Get the flags of the spell at a certain index in a player's latest spellbook changes. + * + * \param pid The player ID whose spellbook changes should be used. + * \param i The index of the spell. + * \return The spell flags. + */ + static int GetSpellFlags(unsigned short pid, unsigned int i) noexcept; + + /** + * \brief Get the number of effects on the spell at a certain index in a player's latest spellbook changes. + * + * \param pid The player ID whose spellbook changes should be used. + * \param i The index of the spell. + * \return The spell effect count. + */ + static unsigned int GetSpellEffectCount(unsigned short pid, unsigned int i) noexcept; + + /** + * \brief Get the effectId of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes. + * + * \param pid The player ID whose spellbook changes should be used. + * \param i The index of the spell. + * \param j The index of the effect. + * \return The effectId. + */ + static short GetSpellEffectId(unsigned short pid, unsigned int i, unsigned int j) noexcept; + + /** + * \brief Get the affected skill of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes. + * + * \param pid The player ID whose spellbook changes should be used. + * \param i The index of the spell. + * \param j The index of the effect. + * \return The affected skill. + */ + static signed char GetSpellEffectSkill(unsigned short pid, unsigned int i, unsigned int j) noexcept; + + /** + * \brief Get the affected attribute of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes. + * + * \param pid The player ID whose spellbook changes should be used. + * \param i The index of the spell. + * \param j The index of the effect. + * \return The affected attribute. + */ + static signed char GetSpellEffectAttribute(unsigned short pid, unsigned int i, unsigned int j) noexcept; + + /** + * \brief Get the range of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes. + * + * \param pid The player ID whose spellbook changes should be used. + * \param i The index of the spell. + * \param j The index of the effect. + * \return The range. + */ + static int GetSpellEffectRange(unsigned short pid, unsigned int i, unsigned int j) noexcept; + + /** + * \brief Get the area of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes. + * + * \param pid The player ID whose spellbook changes should be used. + * \param i The index of the spell. + * \param j The index of the effect. + * \return The area. + */ + static int GetSpellEffectArea(unsigned short pid, unsigned int i, unsigned int j) noexcept; + + /** + * \brief Get the duration of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes. + * + * \param pid The player ID whose spellbook changes should be used. + * \param i The index of the spell. + * \param j The index of the effect. + * \return The duration. + */ + static int GetSpellEffectDuration(unsigned short pid, unsigned int i, unsigned int j) noexcept; + + /** + * \brief Get the minimum magnitude of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes. + * + * \param pid The player ID whose spellbook changes should be used. + * \param i The index of the spell. + * \param j The index of the effect. + * \return The minimum magnitude. + */ + static int GetSpellEffectMagnMin(unsigned short pid, unsigned int i, unsigned int j) noexcept; + + /** + * \brief Get the maximum magnitude of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes. + * + * \param pid The player ID whose spellbook changes should be used. + * \param i The index of the spell. + * \param j The index of the effect. + * \return The maximum magnitude. + */ + static int GetSpellEffectMagnMax(unsigned short pid, unsigned int i, unsigned int j) noexcept; + /** * \brief Send a PlayerSpellbook packet with a player's recorded spellbook changes. * diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index e4bc4fda7..ecd6cfdef 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -648,8 +648,16 @@ void LocalPlayer::addSpells() MWMechanics::Spells &ptrSpells = ptrPlayer.getClass().getCreatureStats(ptrPlayer).getSpells(); for (const auto &spell : spellbookChanges.spells) - ptrSpells.add(spell.mId); - + { + if(spell.mId.find("$dynamic") != string::npos) + { + //custom spell + MWBase::Environment::get().getWorld()->createRecord(spell); + ptrSpells.add(&spell); + }else{ + ptrSpells.add(spell.mId); + } + } } void LocalPlayer::addJournalItems() @@ -1130,12 +1138,24 @@ void LocalPlayer::sendSpellRemoval(std::string id) void LocalPlayer::sendSpellAddition(const ESM::Spell &spell) { - LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Not implemented."); + spellbookChanges.spells.clear(); + + spellbookChanges.spells.push_back(spell); + + spellbookChanges.action = SpellbookChanges::ADD; + getNetworking()->getPlayerPacket(ID_PLAYER_SPELLBOOK)->setPlayer(this); + getNetworking()->getPlayerPacket(ID_PLAYER_SPELLBOOK)->Send(); } void LocalPlayer::sendSpellRemoval(const ESM::Spell &spell) { - LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Not implemented."); + spellbookChanges.spells.clear(); + + spellbookChanges.spells.push_back(spell); + + spellbookChanges.action = SpellbookChanges::REMOVE; + getNetworking()->getPlayerPacket(ID_PLAYER_SPELLBOOK)->setPlayer(this); + getNetworking()->getPlayerPacket(ID_PLAYER_SPELLBOOK)->Send(); } void LocalPlayer::sendJournalEntry(const std::string& quest, int index, const MWWorld::Ptr& actor) diff --git a/components/openmw-mp/Packets/Player/PacketPlayerSpellbook.cpp b/components/openmw-mp/Packets/Player/PacketPlayerSpellbook.cpp index 724885eb4..b9737390d 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerSpellbook.cpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerSpellbook.cpp @@ -31,6 +31,40 @@ void PacketPlayerSpellbook::Packet(RakNet::BitStream *bs, bool send) RW(spell.mId, send, 1); + if(spell.mId.find("$dynamic") != string::npos) + { + RW(spell.mName, send, 1); + + RW(spell.mData.mType, send, 1); + RW(spell.mData.mCost, send, 1); + RW(spell.mData.mFlags, send, 1); + + int effectCount = 0; + if (send) + effectCount = spell.mEffects.mList.size(); + + RW(effectCount, send, 1); + + for (unsigned int j = 0; j < effectCount; j++) + { + ESM::ENAMstruct effect; + if (send) + effect = spell.mEffects.mList.at(j); + + RW(effect.mEffectID, send, 1); + RW(effect.mSkill, send, 1); + RW(effect.mAttribute, send, 1); + RW(effect.mRange, send, 1); + RW(effect.mArea, send, 1); + RW(effect.mDuration, send, 1); + RW(effect.mMagnMin, send, 1); + RW(effect.mMagnMax, send, 1); + + if(!send) + spell.mEffects.mList.push_back(effect); + } + } + if (!send) player->spellbookChanges.spells.push_back(spell); }