osb/source/game/StarArmorWearer.cpp

376 lines
13 KiB
C++
Raw Normal View History

2023-06-20 04:33:09 +00:00
#include "StarArmorWearer.hpp"
#include "StarRoot.hpp"
#include "StarItemDatabase.hpp"
#include "StarArmors.hpp"
#include "StarCasting.hpp"
#include "StarImageProcessing.hpp"
#include "StarLiquidItem.hpp"
#include "StarMaterialItem.hpp"
#include "StarObject.hpp"
#include "StarTools.hpp"
#include "StarActivatableItem.hpp"
#include "StarObjectItem.hpp"
#include "StarAssets.hpp"
#include "StarObjectDatabase.hpp"
#include "StarWorld.hpp"
namespace Star {
2023-06-25 08:12:54 +00:00
ArmorWearer::ArmorWearer() : m_lastNude(true) {
2023-06-20 04:33:09 +00:00
addNetElement(&m_headItemDataNetState);
addNetElement(&m_chestItemDataNetState);
addNetElement(&m_legsItemDataNetState);
addNetElement(&m_backItemDataNetState);
addNetElement(&m_headCosmeticItemDataNetState);
addNetElement(&m_chestCosmeticItemDataNetState);
addNetElement(&m_legsCosmeticItemDataNetState);
addNetElement(&m_backCosmeticItemDataNetState);
2023-06-25 08:12:54 +00:00
2023-10-25 04:30:31 +00:00
reset();
2023-06-20 04:33:09 +00:00
}
2023-06-24 13:38:27 +00:00
void ArmorWearer::setupHumanoidClothingDrawables(Humanoid& humanoid, bool forceNude) {
2023-06-25 08:12:54 +00:00
bool nudeChanged = m_lastNude != forceNude;
if (nudeChanged)
2023-06-24 13:38:27 +00:00
m_lastNude = forceNude;
2023-06-25 08:12:54 +00:00
bool headNeedsSync = nudeChanged || m_headNeedsSync;
bool chestNeedsSync = nudeChanged || m_chestNeedsSync;
bool legsNeedsSync = nudeChanged || m_legsNeedsSync;
bool backNeedsSync = nudeChanged || m_backNeedsSync;
2023-06-24 13:38:27 +00:00
2023-06-20 04:33:09 +00:00
bool bodyHidden = false;
if (m_headCosmeticItem && !forceNude) {
2023-06-25 08:12:54 +00:00
if (headNeedsSync) {
humanoid.setHeadArmorFrameset(m_headCosmeticItem->frameset(humanoid.identity().gender));
humanoid.setHeadArmorDirectives(m_headCosmeticItem->directives());
humanoid.setHelmetMaskDirectives(m_headCosmeticItem->maskDirectives());
}
2023-06-20 04:33:09 +00:00
bodyHidden = bodyHidden || m_headCosmeticItem->hideBody();
} else if (m_headItem && !forceNude) {
2023-06-25 08:12:54 +00:00
if (headNeedsSync) {
humanoid.setHeadArmorFrameset(m_headItem->frameset(humanoid.identity().gender));
humanoid.setHeadArmorDirectives(m_headItem->directives());
humanoid.setHelmetMaskDirectives(m_headItem->maskDirectives());
}
2023-06-20 04:33:09 +00:00
bodyHidden = bodyHidden || m_headItem->hideBody();
} else {
humanoid.setHeadArmorFrameset("");
humanoid.setHelmetMaskDirectives("");
}
if (m_chestCosmeticItem && !forceNude) {
2023-06-25 08:12:54 +00:00
if (chestNeedsSync) {
humanoid.setBackSleeveFrameset(m_chestCosmeticItem->backSleeveFrameset(humanoid.identity().gender));
humanoid.setFrontSleeveFrameset(m_chestCosmeticItem->frontSleeveFrameset(humanoid.identity().gender));
humanoid.setChestArmorFrameset(m_chestCosmeticItem->bodyFrameset(humanoid.identity().gender));
humanoid.setChestArmorDirectives(m_chestCosmeticItem->directives());
}
2023-06-20 04:33:09 +00:00
bodyHidden = bodyHidden || m_chestCosmeticItem->hideBody();
} else if (m_chestItem && !forceNude) {
2023-06-25 08:12:54 +00:00
if (chestNeedsSync) {
humanoid.setBackSleeveFrameset(m_chestItem->backSleeveFrameset(humanoid.identity().gender));
humanoid.setFrontSleeveFrameset(m_chestItem->frontSleeveFrameset(humanoid.identity().gender));
humanoid.setChestArmorFrameset(m_chestItem->bodyFrameset(humanoid.identity().gender));
humanoid.setChestArmorDirectives(m_chestItem->directives());
}
2023-06-20 04:33:09 +00:00
bodyHidden = bodyHidden || m_chestItem->hideBody();
} else {
humanoid.setBackSleeveFrameset("");
humanoid.setFrontSleeveFrameset("");
humanoid.setChestArmorFrameset("");
}
if (m_legsCosmeticItem && !forceNude) {
2023-06-25 08:12:54 +00:00
if (legsNeedsSync) {
humanoid.setLegsArmorFrameset(m_legsCosmeticItem->frameset(humanoid.identity().gender));
humanoid.setLegsArmorDirectives(m_legsCosmeticItem->directives());
}
2023-06-20 04:33:09 +00:00
bodyHidden = bodyHidden || m_legsCosmeticItem->hideBody();
} else if (m_legsItem && !forceNude) {
2023-06-25 08:12:54 +00:00
if (legsNeedsSync) {
humanoid.setLegsArmorFrameset(m_legsItem->frameset(humanoid.identity().gender));
humanoid.setLegsArmorDirectives(m_legsItem->directives());
}
2023-06-20 04:33:09 +00:00
bodyHidden = bodyHidden || m_legsItem->hideBody();
} else {
humanoid.setLegsArmorFrameset("");
}
if (m_backCosmeticItem && !forceNude) {
2023-06-25 08:12:54 +00:00
if (backNeedsSync) {
humanoid.setBackArmorFrameset(m_backCosmeticItem->frameset(humanoid.identity().gender));
humanoid.setBackArmorDirectives(m_backCosmeticItem->directives());
}
2023-06-20 04:33:09 +00:00
bodyHidden = bodyHidden || m_backCosmeticItem->hideBody();
} else if (m_backItem && !forceNude) {
2023-06-25 08:12:54 +00:00
if (backNeedsSync) {
humanoid.setBackArmorFrameset(m_backItem->frameset(humanoid.identity().gender));
humanoid.setBackArmorDirectives(m_backItem->directives());
}
2023-06-20 04:33:09 +00:00
bodyHidden = bodyHidden || m_backItem->hideBody();
} else {
humanoid.setBackArmorFrameset("");
}
2023-06-25 08:12:54 +00:00
m_headNeedsSync = m_chestNeedsSync = m_legsNeedsSync = m_backNeedsSync = false;
2023-06-20 04:33:09 +00:00
humanoid.setBodyHidden(bodyHidden);
}
void ArmorWearer::effects(EffectEmitter& effectEmitter) {
if (auto item = as<EffectSourceItem>(m_headCosmeticItem))
effectEmitter.addEffectSources("headArmor", item->effectSources());
else if (auto item = as<EffectSourceItem>(m_headItem))
effectEmitter.addEffectSources("headArmor", item->effectSources());
if (auto item = as<EffectSourceItem>(m_chestCosmeticItem))
effectEmitter.addEffectSources("chestArmor", item->effectSources());
else if (auto item = as<EffectSourceItem>(m_chestItem))
effectEmitter.addEffectSources("chestArmor", item->effectSources());
if (auto item = as<EffectSourceItem>(m_legsCosmeticItem))
effectEmitter.addEffectSources("legsArmor", item->effectSources());
else if (auto item = as<EffectSourceItem>(m_legsItem))
effectEmitter.addEffectSources("legsArmor", item->effectSources());
if (auto item = as<EffectSourceItem>(m_backCosmeticItem))
effectEmitter.addEffectSources("backArmor", item->effectSources());
else if (auto item = as<EffectSourceItem>(m_backItem))
effectEmitter.addEffectSources("backArmor", item->effectSources());
}
2023-10-25 04:30:31 +00:00
void ArmorWearer::reset() {
m_headNeedsSync = m_chestNeedsSync = m_legsNeedsSync = m_backNeedsSync = true;
m_headItem .reset();
m_chestItem.reset();
m_legsItem .reset();
m_backItem .reset();
m_headCosmeticItem .reset();
m_chestCosmeticItem.reset();
m_legsCosmeticItem .reset();
m_backCosmeticItem .reset();
}
2023-06-20 04:33:09 +00:00
Json ArmorWearer::diskStore() const {
JsonObject res;
if (m_headItem)
res["headItem"] = m_headItem->descriptor().diskStore();
if (m_chestItem)
res["chestItem"] = m_chestItem->descriptor().diskStore();
if (m_legsItem)
res["legsItem"] = m_legsItem->descriptor().diskStore();
if (m_backItem)
res["backItem"] = m_backItem->descriptor().diskStore();
if (m_headCosmeticItem)
res["headCosmeticItem"] = m_headCosmeticItem->descriptor().diskStore();
if (m_chestCosmeticItem)
res["chestCosmeticItem"] = m_chestCosmeticItem->descriptor().diskStore();
if (m_legsCosmeticItem)
res["legsCosmeticItem"] = m_legsCosmeticItem->descriptor().diskStore();
if (m_backCosmeticItem)
res["backCosmeticItem"] = m_backCosmeticItem->descriptor().diskStore();
return res;
}
void ArmorWearer::diskLoad(Json const& diskStore) {
auto itemDb = Root::singleton().itemDatabase();
m_headItem = as<HeadArmor>(itemDb->diskLoad(diskStore.get("headItem", {})));
m_chestItem = as<ChestArmor>(itemDb->diskLoad(diskStore.get("chestItem", {})));
m_legsItem = as<LegsArmor>(itemDb->diskLoad(diskStore.get("legsItem", {})));
m_backItem = as<BackArmor>(itemDb->diskLoad(diskStore.get("backItem", {})));
m_headCosmeticItem = as<HeadArmor>(itemDb->diskLoad(diskStore.get("headCosmeticItem", {})));
m_chestCosmeticItem = as<ChestArmor>(itemDb->diskLoad(diskStore.get("chestCosmeticItem", {})));
m_legsCosmeticItem = as<LegsArmor>(itemDb->diskLoad(diskStore.get("legsCosmeticItem", {})));
m_backCosmeticItem = as<BackArmor>(itemDb->diskLoad(diskStore.get("backCosmeticItem", {})));
}
List<PersistentStatusEffect> ArmorWearer::statusEffects() const {
List<PersistentStatusEffect> statusEffects;
auto addStatusFromItem = [&](ItemPtr const& item) {
if (auto effectItem = as<StatusEffectItem>(item))
statusEffects.appendAll(effectItem->statusEffects());
};
addStatusFromItem(m_headItem);
addStatusFromItem(m_chestItem);
addStatusFromItem(m_legsItem);
addStatusFromItem(m_backItem);
return statusEffects;
}
void ArmorWearer::setHeadItem(HeadArmorPtr headItem) {
2023-06-25 04:00:41 +00:00
if (Item::itemsEqual(m_headItem, headItem))
2023-06-24 13:38:27 +00:00
return;
2023-06-20 04:33:09 +00:00
m_headItem = headItem;
2023-06-25 08:12:54 +00:00
m_headNeedsSync |= !m_headCosmeticItem;
2023-06-20 04:33:09 +00:00
}
void ArmorWearer::setHeadCosmeticItem(HeadArmorPtr headCosmeticItem) {
2023-06-25 04:00:41 +00:00
if (Item::itemsEqual(m_headCosmeticItem, headCosmeticItem))
2023-06-24 13:38:27 +00:00
return;
2023-06-20 04:33:09 +00:00
m_headCosmeticItem = headCosmeticItem;
2023-06-25 08:12:54 +00:00
m_headNeedsSync = true;
2023-06-20 04:33:09 +00:00
}
void ArmorWearer::setChestItem(ChestArmorPtr chestItem) {
2023-06-25 04:00:41 +00:00
if (Item::itemsEqual(m_chestItem, chestItem))
2023-06-24 13:38:27 +00:00
return;
2023-06-20 04:33:09 +00:00
m_chestItem = chestItem;
2023-06-25 08:12:54 +00:00
m_chestNeedsSync |= !m_chestCosmeticItem;
}
void ArmorWearer::setChestCosmeticItem(ChestArmorPtr chestCosmeticItem) {
if (Item::itemsEqual(m_chestCosmeticItem, chestCosmeticItem))
return;
m_chestCosmeticItem = chestCosmeticItem;
m_chestNeedsSync = true;
2023-06-20 04:33:09 +00:00
}
void ArmorWearer::setLegsItem(LegsArmorPtr legsItem) {
2023-06-25 04:00:41 +00:00
if (Item::itemsEqual(m_legsItem, legsItem))
2023-06-24 13:38:27 +00:00
return;
2023-06-20 04:33:09 +00:00
m_legsItem = legsItem;
2023-06-25 08:12:54 +00:00
m_legsNeedsSync |= !m_legsCosmeticItem;
2023-06-20 04:33:09 +00:00
}
void ArmorWearer::setLegsCosmeticItem(LegsArmorPtr legsCosmeticItem) {
2023-06-25 04:00:41 +00:00
if (Item::itemsEqual(m_legsCosmeticItem, legsCosmeticItem))
2023-06-24 13:38:27 +00:00
return;
2023-06-20 04:33:09 +00:00
m_legsCosmeticItem = legsCosmeticItem;
2023-06-25 08:12:54 +00:00
m_legsNeedsSync = true;
2023-06-20 04:33:09 +00:00
}
void ArmorWearer::setBackItem(BackArmorPtr backItem) {
2023-06-25 04:00:41 +00:00
if (Item::itemsEqual(m_backItem, backItem))
2023-06-24 13:38:27 +00:00
return;
2023-06-20 04:33:09 +00:00
m_backItem = backItem;
2023-06-25 08:12:54 +00:00
m_backNeedsSync |= !m_backCosmeticItem;
2023-06-20 04:33:09 +00:00
}
void ArmorWearer::setBackCosmeticItem(BackArmorPtr backCosmeticItem) {
2023-06-25 04:00:41 +00:00
if (Item::itemsEqual(m_backCosmeticItem, backCosmeticItem))
2023-06-24 13:38:27 +00:00
return;
2023-06-20 04:33:09 +00:00
m_backCosmeticItem = backCosmeticItem;
2023-06-25 08:12:54 +00:00
m_backNeedsSync = true;
2023-06-20 04:33:09 +00:00
}
HeadArmorPtr ArmorWearer::headItem() const {
return m_headItem;
}
HeadArmorPtr ArmorWearer::headCosmeticItem() const {
return m_headCosmeticItem;
}
ChestArmorPtr ArmorWearer::chestItem() const {
return m_chestItem;
}
ChestArmorPtr ArmorWearer::chestCosmeticItem() const {
return m_chestCosmeticItem;
}
LegsArmorPtr ArmorWearer::legsItem() const {
return m_legsItem;
}
LegsArmorPtr ArmorWearer::legsCosmeticItem() const {
return m_legsCosmeticItem;
}
BackArmorPtr ArmorWearer::backItem() const {
return m_backItem;
}
BackArmorPtr ArmorWearer::backCosmeticItem() const {
return m_backCosmeticItem;
}
ItemDescriptor ArmorWearer::headItemDescriptor() const {
if (m_headItem)
return m_headItem->descriptor();
return {};
}
ItemDescriptor ArmorWearer::headCosmeticItemDescriptor() const {
if (m_headCosmeticItem)
return m_headCosmeticItem->descriptor();
return {};
}
ItemDescriptor ArmorWearer::chestItemDescriptor() const {
if (m_chestItem)
return m_chestItem->descriptor();
return {};
}
ItemDescriptor ArmorWearer::chestCosmeticItemDescriptor() const {
if (m_chestCosmeticItem)
return m_chestCosmeticItem->descriptor();
return {};
}
ItemDescriptor ArmorWearer::legsItemDescriptor() const {
if (m_legsItem)
return m_legsItem->descriptor();
return {};
}
ItemDescriptor ArmorWearer::legsCosmeticItemDescriptor() const {
if (m_legsCosmeticItem)
return m_legsCosmeticItem->descriptor();
return {};
}
ItemDescriptor ArmorWearer::backItemDescriptor() const {
if (m_backItem)
return m_backItem->descriptor();
return {};
}
ItemDescriptor ArmorWearer::backCosmeticItemDescriptor() const {
if (m_backCosmeticItem)
return m_backCosmeticItem->descriptor();
return {};
}
void ArmorWearer::netElementsNeedLoad(bool) {
auto itemDatabase = Root::singleton().itemDatabase();
if (m_headCosmeticItemDataNetState.pullUpdated())
2023-06-25 08:12:54 +00:00
m_headNeedsSync |= itemDatabase->loadItem(m_headCosmeticItemDataNetState.get(), m_headCosmeticItem);
2023-06-20 04:33:09 +00:00
if (m_chestCosmeticItemDataNetState.pullUpdated())
2023-06-25 08:12:54 +00:00
m_chestNeedsSync |= itemDatabase->loadItem(m_chestCosmeticItemDataNetState.get(), m_chestCosmeticItem);
2023-06-20 04:33:09 +00:00
if (m_legsCosmeticItemDataNetState.pullUpdated())
2023-06-25 08:12:54 +00:00
m_legsNeedsSync |= itemDatabase->loadItem(m_legsCosmeticItemDataNetState.get(), m_legsCosmeticItem);
2023-06-20 04:33:09 +00:00
if (m_backCosmeticItemDataNetState.pullUpdated())
2023-06-25 08:12:54 +00:00
m_backNeedsSync |= itemDatabase->loadItem(m_backCosmeticItemDataNetState.get(), m_backCosmeticItem);
2023-06-24 13:38:27 +00:00
2023-06-25 08:12:54 +00:00
if (m_headItemDataNetState.pullUpdated())
m_headNeedsSync |= !m_headCosmeticItem && itemDatabase->loadItem(m_headItemDataNetState.get(), m_headItem);
if (m_chestItemDataNetState.pullUpdated())
m_chestNeedsSync |= !m_chestCosmeticItem && itemDatabase->loadItem(m_chestItemDataNetState.get(), m_chestItem);
if (m_legsItemDataNetState.pullUpdated())
m_legsNeedsSync |= !m_legsCosmeticItem && itemDatabase->loadItem(m_legsItemDataNetState.get(), m_legsItem);
if (m_backItemDataNetState.pullUpdated())
m_backNeedsSync |= !m_backCosmeticItem && itemDatabase->loadItem(m_backItemDataNetState.get(), m_backItem);
2023-06-20 04:33:09 +00:00
}
void ArmorWearer::netElementsNeedStore() {
auto itemDatabase = Root::singleton().itemDatabase();
m_headItemDataNetState.set(itemSafeDescriptor(m_headItem));
m_chestItemDataNetState.set(itemSafeDescriptor(m_chestItem));
m_legsItemDataNetState.set(itemSafeDescriptor(m_legsItem));
m_backItemDataNetState.set(itemSafeDescriptor(m_backItem));
m_headCosmeticItemDataNetState.set(itemSafeDescriptor(m_headCosmeticItem));
m_chestCosmeticItemDataNetState.set(itemSafeDescriptor(m_chestCosmeticItem));
m_legsCosmeticItemDataNetState.set(itemSafeDescriptor(m_legsCosmeticItem));
m_backCosmeticItemDataNetState.set(itemSafeDescriptor(m_backCosmeticItem));
}
}