#include "framework.h" #include "GameScriptItemInfo.h" #include "items.h" #include "objectslist.h" #include "level.h" #include "setup.h" #include "lot.h" #include "GameScriptPosition.h" #include "GameScriptRotation.h" extern bool const WarningsAsErrors; GameScriptItemInfo::GameScriptItemInfo(short num) : m_item{ &g_Level.Items[num]}, m_num { num } {}; GameScriptItemInfo::GameScriptItemInfo(GameScriptItemInfo&& other) noexcept : m_item { std::exchange(other.m_item, nullptr) }, m_num{ std::exchange(other.m_num, -1) } {}; // todo.. how to check if item is killed outside of script? GameScriptItemInfo::~GameScriptItemInfo() { // todo.. see if there's a better default state than -1 if (m_num > -1) { KillItem(m_num); } } void GameScriptItemInfo::Register(sol::state * state) { state->new_usertype("ItemInfo", "new", sol::overload(&GameScriptItemInfo::Create, &GameScriptItemInfo::CreateEmpty), "Init", &GameScriptItemInfo::Init, "GetPos", &GameScriptItemInfo::GetPos, "GetRot", &GameScriptItemInfo::GetRot, "GetCurrentAnim", &GameScriptItemInfo::GetCurrentAnim, "GetRequiredAnim", &GameScriptItemInfo::GetRequiredAnim, "GetGoalAnim", &GameScriptItemInfo::GetGoalAnim, "GetHP", &GameScriptItemInfo::GetHP, "GetOCB", &GameScriptItemInfo::GetOCB, "GetItemFlags", &GameScriptItemInfo::GetItemFlags, "GetAIBits", &GameScriptItemInfo::GetAIBits, "GetStatus", &GameScriptItemInfo::GetStatus, "GetHitStatus", &GameScriptItemInfo::GetHitStatus, "GetActive", &GameScriptItemInfo::GetActive, "GetRoom", &GameScriptItemInfo::GetRoom, "SetPos", &GameScriptItemInfo::SetPos, "SetRot", &GameScriptItemInfo::SetRot, "SetCurrentAnim", &GameScriptItemInfo::SetCurrentAnim, "SetRequiredAnim", &GameScriptItemInfo::SetRequiredAnim, "SetGoalAnim", &GameScriptItemInfo::SetGoalAnim, "SetHP", &GameScriptItemInfo::SetHP, "SetOCB", &GameScriptItemInfo::SetOCB, "SetItemFlags", &GameScriptItemInfo::SetItemFlags, "SetAIBits", &GameScriptItemInfo::SetAIBits, "SetStatus", &GameScriptItemInfo::SetStatus, "SetHitStatus", &GameScriptItemInfo::SetHitStatus, "SetActive", &GameScriptItemInfo::SetActive, "SetRoom", &GameScriptItemInfo::SetRoom, "Enable", &GameScriptItemInfo::EnableItem, "Disable", &GameScriptItemInfo::DisableItem); } std::unique_ptr GameScriptItemInfo::CreateEmpty() { short num = CreateItem(); ITEM_INFO * item = &g_Level.Items[num]; item->objectNumber = ID_SMALLMEDI_ITEM; return std::make_unique(num); } std::unique_ptr GameScriptItemInfo::Create( GameScriptPosition pos, GameScriptRotation rot, short room, short currentAnim, short requiredAnim, short goalAnim, short hp, short ocb, sol::as_table_t> itemFlags, byte aiBits, short status, bool active, bool hitStatus ) { short num = CreateItem(); auto ptr = std::make_unique(num); ITEM_INFO * item = &g_Level.Items[num]; ptr->SetPos(pos); ptr->SetRot(rot); ptr->SetRoom(room); //make it a big medipack by default for now item->objectNumber = ID_BIGMEDI_ITEM; InitialiseItem(num); ptr->SetCurrentAnim(currentAnim); ptr->SetRequiredAnim(requiredAnim); ptr->SetGoalAnim(requiredAnim); ptr->SetHP(hp); ptr->SetOCB(ocb); ptr->SetItemFlags(itemFlags); ptr->SetAIBits(aiBits); ptr->SetStatus(status); ptr->SetActive(active); ptr->SetHitStatus(hitStatus); return ptr; } void GameScriptItemInfo::Init() { InitialiseItem(m_num); } GameScriptPosition GameScriptItemInfo::GetPos() const { return GameScriptPosition( m_item->pos.xPos, m_item->pos.yPos, m_item->pos.zPos); } void GameScriptItemInfo::SetPos(GameScriptPosition const& pos) { m_item->pos.xPos = pos.GetX(); m_item->pos.yPos = pos.GetY(); m_item->pos.zPos = pos.GetZ(); } GameScriptRotation GameScriptItemInfo::GetRot() const { return GameScriptRotation( m_item->pos.xRot, m_item->pos.yRot, m_item->pos.zRot); } void GameScriptItemInfo::SetRot(GameScriptRotation const& rot) { m_item->pos.xRot = rot.GetX(); m_item->pos.yRot = rot.GetY(); m_item->pos.zRot = rot.GetZ(); } short GameScriptItemInfo::GetGoalAnim() const { return m_item->goalAnimState; } void GameScriptItemInfo::SetGoalAnim(short state) { m_item->goalAnimState = state; } short GameScriptItemInfo::GetHP() const { return(m_item->hitPoints); } void GameScriptItemInfo::SetHP(short hp) { if (hp < 0 || hp > Objects[m_item->objectNumber].hitPoints) { if (WarningsAsErrors) throw std::runtime_error("invalid HP"); if (hp < 0) { hp = 0; } else if (hp > Objects[m_item->objectNumber].hitPoints) { hp = Objects[m_item->objectNumber].hitPoints; } } m_item->hitPoints = hp; } short GameScriptItemInfo::GetOCB() const { return m_item->triggerFlags; } void GameScriptItemInfo::SetOCB(short ocb) { m_item->triggerFlags = ocb; } byte GameScriptItemInfo::GetAIBits() const { return m_item->aiBits; } void GameScriptItemInfo::SetAIBits(byte bits) { m_item->aiBits = bits; } sol::as_table_t> GameScriptItemInfo::GetItemFlags() const { std::array ret{}; memcpy(ret.data(), m_item->itemFlags, sizeof(m_item->itemFlags)); return ret; } void GameScriptItemInfo::SetItemFlags(sol::as_table_t> const& arr) { memcpy(m_item->itemFlags, arr.value().data(), sizeof(m_item->itemFlags)); } short GameScriptItemInfo::GetCurrentAnim() const { return m_item->currentAnimState; } void GameScriptItemInfo::SetCurrentAnim(short anim) { m_item->currentAnimState = anim; } short GameScriptItemInfo::GetRequiredAnim() const { return m_item->requiredAnimState; } void GameScriptItemInfo::SetRequiredAnim(short anim) { m_item->requiredAnimState = anim; } short GameScriptItemInfo::GetStatus() const { return m_item->status; } void GameScriptItemInfo::SetStatus(short status) { m_item->status = status; } bool GameScriptItemInfo::GetActive() const { return m_item->active; } void GameScriptItemInfo::SetActive(bool active) { m_item->active = active; } bool GameScriptItemInfo::GetHitStatus() const { return m_item->hitStatus; } void GameScriptItemInfo::SetHitStatus(bool hitStatus) { m_item->hitStatus = hitStatus; } short GameScriptItemInfo::GetRoom() const { return m_item->roomNumber; } void GameScriptItemInfo::SetRoom(short room) { if (room < 0 || room >= g_Level.Rooms.size()) { if (WarningsAsErrors) throw std::runtime_error("invalid room number"); return; } m_item->roomNumber = room; } void GameScriptItemInfo::EnableItem() { if (!m_item->active) { if (Objects[m_item->objectNumber].intelligent) { if (m_item->status == ITEM_DEACTIVATED) { m_item->touchBits = 0; m_item->status = ITEM_ACTIVE; AddActiveItem(m_num); EnableBaddieAI(m_num, 1); } else if (m_item->status == ITEM_INVISIBLE) { m_item->touchBits = 0; if (EnableBaddieAI(m_num, 0)) m_item->status = ITEM_ACTIVE; else m_item->status = ITEM_INVISIBLE; AddActiveItem(m_num); } } else { m_item->touchBits = 0; AddActiveItem(m_num); m_item->status = ITEM_ACTIVE; } } } void GameScriptItemInfo::DisableItem() { if (m_item->active) { if (Objects[m_item->objectNumber].intelligent) { if (m_item->status == ITEM_ACTIVE) { m_item->touchBits = 0; m_item->status = ITEM_DEACTIVATED; RemoveActiveItem(m_num); DisableBaddieAI(m_num); } } else { m_item->touchBits = 0; RemoveActiveItem(m_num); m_item->status = ITEM_DEACTIVATED; } } }