Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tile Change Event Stuff #1692

Merged
merged 5 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ https://github.com/nwnxee/unified/compare/build8193.35.40...HEAD
- Events: added event `NWNX_ON_ATTACK_TARGET_CHANGE_{BEFORE|AFTER}` which fires when a creature changes its attack target.
- Events: added `NWNX_ON_PLACEABLE_OPEN_{BEFORE|AFTER}` which fires when player opens a placeable.
- Events: added `NWNX_ON_PLACEABLE_CLOSE_{BEFORE|AFTER}` which fires when player closes a placeable.
- Events: added event `NWNX_ON_CREATURE_TILE_CHANGE_{BEFORE|AFTER}` which fires when a creature changes the tile it's on.
- Tweaks: added `NWNX_TWEAKS_SETAREA_CALLS_SETPOSITION` which will enable firing of the `NWNX_ON_MATERIALCHANGE_*` and `NWNX_ON_CREATURE_TILE_CHANGE_*` events when a creature is first added to an area.

##### New Plugins
- Resources: Adds `RESOURCES_*` variables for adding NWSync as a resource source, and specifying a replacement hak list.
Expand Down
2 changes: 1 addition & 1 deletion Plugins/Events/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ add_plugin(Events
"Events/JournalEvents.cpp"
"Events/LevelEvents.cpp"
"Events/MapEvents.cpp"
"Events/MaterialChangeEvents.cpp"
"Events/TileEvents.cpp"
"Events/ObjectEvents.cpp"
"Events/PartyEvents.cpp"
"Events/PolymorphEvents.cpp"
Expand Down
54 changes: 0 additions & 54 deletions Plugins/Events/Events/MaterialChangeEvents.cpp

This file was deleted.

117 changes: 117 additions & 0 deletions Plugins/Events/Events/TileEvents.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#include "Events.hpp"
#include "API/CAppManager.hpp"
#include "API/CServerExoApp.hpp"
#include "API/CNWSArea.hpp"
#include "API/CNWSObject.hpp"
#include "API/CNWSCreature.hpp"
#include "API/CNWSTile.hpp"

namespace Events {

using namespace NWNXLib;

static Hooks::Hook s_SetPositionMaterialChangeHook;
static Hooks::Hook s_SetPositionTileChangeHook;

static void SetPositionMaterialChangeHook(CNWSObject*, Vector, int32_t);
static void SetPositionTileChangeHook(CNWSObject*, Vector, int32_t);

void TileEvents() __attribute__((constructor));
void TileEvents()
{
InitOnFirstSubscribe("NWNX_ON_MATERIALCHANGE_.*", []() {
s_SetPositionMaterialChangeHook = Hooks::HookFunction(&CNWSObject::SetPosition,
&SetPositionMaterialChangeHook, Hooks::Order::Earliest);
});

InitOnFirstSubscribe("NWNX_ON_CREATURE_TILE_CHANGE_.*", []() {
s_SetPositionTileChangeHook = Hooks::HookFunction(&CNWSObject::SetPosition,
&SetPositionTileChangeHook, Hooks::Order::Earliest);
});
}

void SetPositionMaterialChangeHook(CNWSObject* thisPtr, Vector vPosition, BOOL bDoingCharacterCopy)
{
if (thisPtr->m_nObjectType != API::Constants::ObjectType::Creature)
{
s_SetPositionMaterialChangeHook->CallOriginal<void>(thisPtr, vPosition, bDoingCharacterCopy);
return;
}

if (auto *pCreature = Utils::AsNWSCreature(thisPtr))
{
CNWSArea *pArea = API::Globals::AppManager()->m_pServerExoApp->GetAreaByGameObjectID(pCreature->m_oidArea);
if (!pArea)
pArea = API::Globals::AppManager()->m_pServerExoApp->GetAreaByGameObjectID(pCreature->m_oidDesiredArea);

if (pArea)
{
int32_t oldMaterial = pArea->GetSurfaceMaterial(pCreature->m_vPosition);
int32_t newMaterial = pArea->GetSurfaceMaterial(vPosition);

if (oldMaterial != newMaterial || pCreature->m_vPosition == vPosition)
{
PushEventData("MATERIAL_TYPE", std::to_string(newMaterial));
SignalEvent("NWNX_ON_MATERIALCHANGE_BEFORE", thisPtr->m_idSelf);

s_SetPositionMaterialChangeHook->CallOriginal<void>(thisPtr, vPosition, bDoingCharacterCopy);

PushEventData("MATERIAL_TYPE", std::to_string(newMaterial));
SignalEvent("NWNX_ON_MATERIALCHANGE_AFTER", thisPtr->m_idSelf);

return;
}
}
}

s_SetPositionMaterialChangeHook->CallOriginal<void>(thisPtr, vPosition, bDoingCharacterCopy);
}

void SetPositionTileChangeHook(CNWSObject* thisPtr, Vector vPosition, BOOL bDoingCharacterCopy)
{
if (thisPtr->m_nObjectType != API::Constants::ObjectType::Creature)
{
s_SetPositionTileChangeHook->CallOriginal<void>(thisPtr, vPosition, bDoingCharacterCopy);
return;
}

if (auto *pCreature = Utils::AsNWSCreature(thisPtr))
{
CNWSArea *pArea = API::Globals::AppManager()->m_pServerExoApp->GetAreaByGameObjectID(pCreature->m_oidArea);
if (!pArea)
pArea = API::Globals::AppManager()->m_pServerExoApp->GetAreaByGameObjectID(pCreature->m_oidDesiredArea);

if (pArea)
{
CNWSTile *pOldTile = pArea->GetTile(pCreature->m_vPosition);
CNWSTile *pNewTile = pArea->GetTile(vPosition);

if (pOldTile && pNewTile && (pOldTile != pNewTile || pCreature->m_vPosition == vPosition))
{
PushEventData("OLD_TILE_INDEX", std::to_string(pOldTile->m_nGridX + (pArea->m_nWidth * pOldTile->m_nGridY)));
PushEventData("OLD_TILE_X", std::to_string(pOldTile->m_nGridX));
PushEventData("OLD_TILE_Y", std::to_string(pOldTile->m_nGridY));
PushEventData("NEW_TILE_INDEX", std::to_string(pNewTile->m_nGridX + (pArea->m_nWidth * pNewTile->m_nGridY)));
PushEventData("NEW_TILE_X", std::to_string(pNewTile->m_nGridX));
PushEventData("NEW_TILE_Y", std::to_string(pNewTile->m_nGridY));
SignalEvent("NWNX_ON_CREATURE_TILE_CHANGE_BEFORE", pCreature->m_idSelf);

s_SetPositionTileChangeHook->CallOriginal<void>(thisPtr, vPosition, bDoingCharacterCopy);

PushEventData("OLD_TILE_INDEX", std::to_string(pOldTile->m_nGridX + (pArea->m_nWidth * pOldTile->m_nGridY)));
PushEventData("OLD_TILE_X", std::to_string(pOldTile->m_nGridX));
PushEventData("OLD_TILE_Y", std::to_string(pOldTile->m_nGridY));
PushEventData("NEW_TILE_INDEX", std::to_string(pNewTile->m_nGridX + (pArea->m_nWidth * pNewTile->m_nGridY)));
PushEventData("NEW_TILE_X", std::to_string(pNewTile->m_nGridX));
PushEventData("NEW_TILE_Y", std::to_string(pNewTile->m_nGridY));
SignalEvent("NWNX_ON_CREATURE_TILE_CHANGE_AFTER", pCreature->m_idSelf);

return;
}
}
}

s_SetPositionTileChangeHook->CallOriginal<void>(thisPtr, vPosition, bDoingCharacterCopy);
}

}
17 changes: 17 additions & 0 deletions Plugins/Events/NWScript/nwnx_events.nss
Original file line number Diff line number Diff line change
Expand Up @@ -1696,6 +1696,21 @@ _______________________________________
NEW_TARGET_OBJECT_ID | object | The new attack target. OBJECT_INVALID if there is no new target. Convert to object with StringToObject() |
AUTOMATIC_CHANGE | int | TRUE if the game automatically decided on the new target, FALSE if explicitly chosen |
RETARGETABLE | int | TRUE if the new target can be changed using NWNX_Events_SetEventResult() (Only in BEFORE) |
_______________________________________
## Creature Tile Change Events
- NWNX_ON_CREATURE_TILE_CHANGE_BEFORE
- NWNX_ON_CREATURE_TILE_CHANGE_AFTER

`OBJECT_SELF` = The creature changing tile positions.

Event Data Tag | Type | Notes
----------------------|--------|-------
OLD_TILE_INDEX | int | The index of the old tile. |
OLD_TILE_X | int | The tile grid x position of the old tile. |
OLD_TILE_Y | int | The tile grid y position of the old tile. |
NEW_TILE_INDEX | int | The index of the new tile. |
NEW_TILE_X | int | The tile grid x position of the new tile. |
NEW_TILE_Y | int | The tile grid y position of the new tile. |
_______________________________________
*/

Expand Down Expand Up @@ -2039,6 +2054,8 @@ const string NWNX_ON_AREA_PLAY_BATTLE_MUSIC_BEFORE = "NWNX_ON_AREA_PLAY_BATTLE_M
const string NWNX_ON_AREA_PLAY_BATTLE_MUSIC_AFTER = "NWNX_ON_AREA_PLAY_BATTLE_MUSIC_AFTER";
const string NWNX_ON_ATTACK_TARGET_CHANGE_BEFORE = "NWNX_ON_ATTACK_TARGET_CHANGE_BEFORE";
const string NWNX_ON_ATTACK_TARGET_CHANGE_AFTER = "NWNX_ON_ATTACK_TARGET_CHANGE_AFTER";
const string NWNX_ON_CREATURE_TILE_CHANGE_BEFORE = "NWNX_ON_CREATURE_TILE_CHANGE_BEFORE";
const string NWNX_ON_CREATURE_TILE_CHANGE_AFTER = "NWNX_ON_CREATURE_TILE_CHANGE_AFTER";
/// @}

/// @name Events ObjectType Constants
Expand Down
3 changes: 2 additions & 1 deletion Plugins/Tweaks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ add_plugin(Tweaks
"RangedWeaponsUseOnHitEffectItemProperties.cpp"
"RangedWeaponsUseOnHitCastSpellItemProperties.cpp"
"CastAllOnHitCastSpellItemProperties.cpp"
"FixAutoMapCrash.cpp")
"FixAutoMapCrash.cpp"
"SetAreaCallsSetPosition.cpp")
1 change: 1 addition & 0 deletions Plugins/Tweaks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Tweaks stuff. See below.
| `NWNX_TWEAKS_RANGED_WEAPONS_USE_ON_HIT_CAST_SPELL_ITEM_PROPERTIES` | true or false | Makes all bows, crossbows, and slings use On Hit: Cast Spell item properties (in addition to their ammunition). |
| `NWNX_TWEAKS_CAST_ALL_ON_HIT_CAST_SPELL_ITEM_PROPERTIES` | true or false | Casts all On Hit: Cast Spell item properties on hit, instead of only the first property. |
| `NWNX_TWEAKS_FIX_AUTOMAP_CRASH` | true or false | Fixes a server crash that happens when automap data is outdated for a player. |
| `NWNX_TWEAKS_SETAREA_CALLS_SETPOSITION` | true or false | If enabled, a creature getting added to an area will fire the `NWNX_ON_MATERIALCHANGE_*` and `NWNX_ON_CREATURE_TILE_CHANGE_*` events. |

## Environment variable values

Expand Down
32 changes: 32 additions & 0 deletions Plugins/Tweaks/SetAreaCallsSetPosition.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include "nwnx.hpp"
#include "API/CNWSArea.hpp"
#include "API/CNWSObject.hpp"
#include "API/CNWSCreature.hpp"


namespace Tweaks {

using namespace NWNXLib;
using namespace NWNXLib::API;

void SetAreaCallsSetPosition() __attribute__((constructor));
void SetAreaCallsSetPosition()
{
if (!Config::Get<bool>("SETAREA_CALLS_SETPOSITION", false))
return;

LOG_INFO("Calling SetPosition() after SetArea().");

static Hooks::Hook s_SetAreaHook = Hooks::HookFunction(&CNWSObject::SetArea,+[](CNWSObject *pThis, CNWSArea *pArea) -> void
{
s_SetAreaHook->CallOriginal<void>(pThis, pArea);

if (pThis->GetArea())
{
if (auto *pCreature = Utils::AsNWSCreature(pThis))
pCreature->SetPosition(pCreature->m_vPosition);
}
}, Hooks::Order::Early);
}

}