Skip to content

Commit

Permalink
Tile Change Event Stuff (#1692)
Browse files Browse the repository at this point in the history
* Rename MaterialChangeEvents.cpp to TileEvents.cpp

* Refactor and simplify `NWNX_ON_MATERIALCHANGE_*`

* Events: add `NWNX_ON_CREATURE_TILE_CHANGE_{BEFORE|AFTER}`

* Tweaks: add `NWNX_TWEAKS_SETAREA_CALLS_SETPOSITION`
  • Loading branch information
Daztek authored Aug 22, 2023
1 parent d0ebd0f commit ddd4834
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 56 deletions.
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);
}

}

0 comments on commit ddd4834

Please sign in to comment.