1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-27 18:15:31 +00:00
openmw-tes3mp/apps/openmw-mp/Script/Functions/Stats.cpp
David Cernat 78441c769a [General] Rework PlayerSkill packets so they are of minimal size
Previously, whenever a single skill value changed for a player, that player then sent a PlayerSkill packet with all values for all 27 skills, plus the player's progress towards the next level and the bonuses to each attribute on the next level up as the result of sklll increases thus far.

This commit makes PlayerSkill contain only the values of specific skills, moves the player's progress towards the next level to PlayerLevel packets, and moves the bonuses to each attribute on the next level up to PlayerAttribute packets.

Players now also send a PlayerSkill packet whenever their progress towards a new point in a skill changes. This was previously avoided so as to not have massive packet spam.

(cherry picked from commit ef79a98544)
2018-04-19 15:18:38 +03:00

555 lines
14 KiB
C++

#include "Stats.hpp"
#include <iostream>
#include <components/esm/attr.hpp>
#include <components/esm/loadskil.hpp>
#include <components/misc/stringops.hpp>
#include <components/openmw-mp/Log.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
using namespace std;
using namespace ESM;
int StatsFunctions::GetAttributeCount() noexcept
{
return Attribute::Length;
}
int StatsFunctions::GetSkillCount() noexcept
{
return Skill::Length;
}
int StatsFunctions::GetAttributeId(const char *name) noexcept
{
for (int x = 0; x < Attribute::Length; x++)
{
if (Misc::StringUtils::ciEqual(name, Attribute::sAttributeNames[x]))
{
return x;
}
}
return -1;
}
int StatsFunctions::GetSkillId(const char *name) noexcept
{
for (int x = 0; x < Skill::Length; x++)
{
if (Misc::StringUtils::ciEqual(name, Skill::sSkillNames[x]))
{
return x;
}
}
return -1;
}
const char *StatsFunctions::GetAttributeName(unsigned short attributeId) noexcept
{
if (attributeId >= Attribute::Length)
return "invalid";
return Attribute::sAttributeNames[attributeId].c_str();
}
const char *StatsFunctions::GetSkillName(unsigned short skillId) noexcept
{
if (skillId >= Skill::Length)
return "invalid";
return Skill::sSkillNames[skillId].c_str();
}
const char *StatsFunctions::GetName(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->npc.mName.c_str();
}
const char *StatsFunctions::GetRace(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->npc.mRace.c_str();
}
const char *StatsFunctions::GetHead(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->npc.mHead.c_str();
}
const char *StatsFunctions::GetHairstyle(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->npc.mHair.c_str();
}
int StatsFunctions::GetIsMale(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, false);
return player->npc.isMale();
}
const char *StatsFunctions::GetBirthsign(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->birthsign.c_str();
}
int StatsFunctions::GetLevel(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->creatureStats.mLevel;
}
int StatsFunctions::GetLevelProgress(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->npcStats.mLevelProgress;
}
double StatsFunctions::GetHealthBase(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->creatureStats.mDynamic[0].mBase;
}
double StatsFunctions::GetHealthCurrent(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->creatureStats.mDynamic[0].mCurrent;
}
double StatsFunctions::GetMagickaBase(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->creatureStats.mDynamic[1].mBase;
}
double StatsFunctions::GetMagickaCurrent(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->creatureStats.mDynamic[1].mCurrent;
}
double StatsFunctions::GetFatigueBase(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->creatureStats.mDynamic[2].mBase;
}
double StatsFunctions::GetFatigueCurrent(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->creatureStats.mDynamic[2].mCurrent;
}
int StatsFunctions::GetAttributeBase(unsigned short pid, unsigned short attributeId) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (attributeId >= Attribute::Length)
return 0;
return player->creatureStats.mAttributes[attributeId].mBase;
}
int StatsFunctions::GetAttributeModifier(unsigned short pid, unsigned short attributeId) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (attributeId >= Attribute::Length)
return 0;
return player->creatureStats.mAttributes[attributeId].mMod;
}
int StatsFunctions::GetSkillBase(unsigned short pid, unsigned short skillId) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (skillId >= Skill::Length)
return 0;
return player->npcStats.mSkills[skillId].mBase;
}
int StatsFunctions::GetSkillModifier(unsigned short pid, unsigned short skillId) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (skillId >= Skill::Length)
return 0;
return player->npcStats.mSkills[skillId].mMod;
}
double StatsFunctions::GetSkillProgress(unsigned short pid, unsigned short skillId) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
if (skillId >= Skill::Length)
return 0;
return player->npcStats.mSkills[skillId].mProgress;
}
int StatsFunctions::GetSkillIncrease(unsigned short pid, unsigned int attributeId) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (attributeId > Attribute::Length)
return 0;
return player->npcStats.mSkillIncrease[attributeId];
}
int StatsFunctions::GetBounty(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->npcStats.mBounty;
}
const char *StatsFunctions::GetDeathReason(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->deathReason.c_str();
}
void StatsFunctions::SetName(unsigned short pid, const char *name) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (player->npc.mName == name)
return;
player->npc.mName = name;
}
void StatsFunctions::SetRace(unsigned short pid, const char *race) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (player->npc.mRace == race)
return;
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Setting race for %s: %s -> %s", player->npc.mName.c_str(),
player->npc.mRace.c_str(), race);
player->npc.mRace = race;
}
void StatsFunctions::SetHead(unsigned short pid, const char *head) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (player->npc.mHead == head)
return;
player->npc.mHead = head;
}
void StatsFunctions::SetHairstyle(unsigned short pid, const char *hairstyle) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (player->npc.mHair == hairstyle)
return;
player->npc.mHair = hairstyle;
}
void StatsFunctions::SetIsMale(unsigned short pid, int state) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->npc.setIsMale(state == true);
}
void StatsFunctions::SetBirthsign(unsigned short pid, const char *sign) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
if (player->birthsign == sign)
return;
player->birthsign = sign;
}
void StatsFunctions::SetResetStats(unsigned short pid, bool resetStats) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->resetStats = resetStats;
}
void StatsFunctions::SetLevel(unsigned short pid, int value) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->creatureStats.mLevel = value;
}
void StatsFunctions::SetLevelProgress(unsigned short pid, int value) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->npcStats.mLevelProgress = value;
}
void StatsFunctions::SetHealthBase(unsigned short pid, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->creatureStats.mDynamic[0].mBase = value;
}
void StatsFunctions::SetHealthCurrent(unsigned short pid, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->creatureStats.mDynamic[0].mCurrent = value;
}
void StatsFunctions::SetMagickaBase(unsigned short pid, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->creatureStats.mDynamic[1].mBase = value;
}
void StatsFunctions::SetMagickaCurrent(unsigned short pid, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->creatureStats.mDynamic[1].mCurrent = value;
}
void StatsFunctions::SetFatigueBase(unsigned short pid, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->creatureStats.mDynamic[2].mBase = value;
}
void StatsFunctions::SetFatigueCurrent(unsigned short pid, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->creatureStats.mDynamic[2].mCurrent = value;
}
void StatsFunctions::SetAttributeBase(unsigned short pid, unsigned short attributeId, int value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (attributeId >= Attribute::Length)
return;
player->creatureStats.mAttributes[attributeId].mBase = value;
}
void StatsFunctions::ClearAttributeModifier(unsigned short pid, unsigned short attributeId) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (attributeId >= Attribute::Length)
return;
player->creatureStats.mAttributes[attributeId].mMod = 0;
}
void StatsFunctions::SetSkillBase(unsigned short pid, unsigned short skillId, int value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (skillId >= Skill::Length)
return;
player->npcStats.mSkills[skillId].mBase = value;
player->skillChanges.skillIndexes.push_back(skillId);
}
void StatsFunctions::ClearSkillModifier(unsigned short pid, unsigned short skillId) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (skillId >= Skill::Length)
return;
player->npcStats.mSkills[skillId].mMod = 0;
player->skillChanges.skillIndexes.push_back(skillId);
}
void StatsFunctions::SetSkillProgress(unsigned short pid, unsigned short skillId, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
if (skillId >= Skill::Length)
return;
player->npcStats.mSkills[skillId].mProgress = value;
player->skillChanges.skillIndexes.push_back(skillId);
}
void StatsFunctions::SetSkillIncrease(unsigned short pid, unsigned int attributeId, int value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (attributeId > Attribute::Length)
return;
player->npcStats.mSkillIncrease[attributeId] = value;
}
void StatsFunctions::SetBounty(unsigned short pid, int value) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->npcStats.mBounty = value;
}
void StatsFunctions::SetCharGenStage(unsigned short pid, int currentStage, int endStage) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->charGenState.currentStage = currentStage;
player->charGenState.endStage = endStage;
player->charGenState.isFinished = false;
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_CHARGEN)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_CHARGEN)->Send(false);
}
void StatsFunctions::SendBaseInfo(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BASEINFO)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BASEINFO)->Send(false);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BASEINFO)->Send(true);
}
void StatsFunctions::SendStatsDynamic(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_STATS_DYNAMIC)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_STATS_DYNAMIC)->Send(false);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_STATS_DYNAMIC)->Send(true);
}
void StatsFunctions::SendAttributes(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_ATTRIBUTE)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_ATTRIBUTE)->Send(false);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_ATTRIBUTE)->Send(true);
}
void StatsFunctions::SendSkills(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SKILL)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SKILL)->Send(false);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SKILL)->Send(true);
player->skillChanges.skillIndexes.clear();
}
void StatsFunctions::SendLevel(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_LEVEL)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_LEVEL)->Send(false);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_LEVEL)->Send(true);
}
void StatsFunctions::SendBounty(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BOUNTY)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BOUNTY)->Send(false);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BOUNTY)->Send(true);
}