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

Events: add NWNX_ON_AREA_PLAY_BATTLE_MUSIC_* #1648

Merged
merged 1 commit into from
May 1, 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ https://github.com/nwnxee/unified/compare/build8193.35.37...HEAD
- Events: added skippable event `NWNX_ON_BROADCAST_SAFE_PROJECTILE_{BEFORE|AFTER}` which fires whenever a projectile VFX is created for ranged weapons and spells.
- Events: added skippable event `NWNX_ON_BROADCAST_ATTACK_OF_OPPORTUNITY_{BEFORE|AFTER}` which allows skipping a creature provoking attacks of opportunities from enemies.
- Events: added skippable event `NWNX_ON_COMBAT_ATTACK_OF_OPPORTUNITY_{BEFORE|AFTER}` which allows stopping a creature from performing an attack of opportunity against a target.
- Events: added skippable event `NWNX_ON_AREA_PLAY_BATTLE_MUSIC_{BEFORE|AFTER}` which allows skipping the starting/stopping of an area's battle music.

##### New Plugins
- N/A
Expand Down
4 changes: 3 additions & 1 deletion NWNXLib/API/FunctionsLinux.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ NWNXLIB_FUNCTION(_ZN10CNWSPlayerD0Ev)
NWNXLIB_FUNCTION(_ZN10CNWSPlayerD1Ev)
NWNXLIB_FUNCTION(_ZN10CNWSModule15LoadModuleStartE10CExoStringiiRKN6NWSync13AdvertisementE)

// Hooking functions that override a virtual functions doesn't work with the new &Class::Function way...
// Hooking functions that override a virtual function doesn't work with the new &Class::Function way...
// .. so we need these!
NWNXLIB_FUNCTION(_ZN11CNWSTrigger12EventHandlerEjjPvjj)
NWNXLIB_FUNCTION(_ZN12CNWSCreature12EventHandlerEjjPvjj)
Expand Down Expand Up @@ -37,4 +37,6 @@ NWNXLIB_FUNCTION(_ZN9CNWSStore8AIUpdateEv)
NWNXLIB_FUNCTION(_ZN21CNWSEffectListHandler15OnEffectAppliedEP10CNWSObjectP11CGameEffecti)
NWNXLIB_FUNCTION(_ZN21CNWSEffectListHandler15OnEffectRemovedEP10CNWSObjectP11CGameEffect)

NWNXLIB_FUNCTION(_ZN16CNWSAmbientSound15PlayBattleMusicEi)

// ***
35 changes: 33 additions & 2 deletions Plugins/Events/Events/CombatEvents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "API/CNWCCMessageData.hpp"
#include "API/CNWSEffectListHandler.hpp"
#include "API/CNWSMessage.hpp"
#include "API/CNWAmbientSound.hpp"
#include "API/CNWSAmbientSound.hpp"

namespace Events {

Expand All @@ -25,6 +27,7 @@ static Hooks::Hook s_BroadcastAttackOfOpportunityCombatEventHook;
static Hooks::Hook s_AddAttackActionsHook;
static Hooks::Hook s_AddAttackOfOpportunityHook;
static Hooks::Hook s_SetBroadcastedAOOToHook;
static Hooks::Hook s_PlayBattleMusicHook;

static void StartCombatRoundHook(CNWSCombatRound*, ObjectID);
static int32_t ApplyDisarmHook(CNWSEffectListHandler*, CNWSObject*, CGameEffect*, BOOL);
Expand All @@ -36,6 +39,7 @@ static void BroadcastAttackOfOpportunityCombatEventHook(CNWSCreature*, ObjectID,
static BOOL AddAttackActionsHook(CNWSCreature*, ObjectID, BOOL, BOOL, BOOL);
static void AddAttackOfOpportunityHook(CNWSCombatRound*, ObjectID);
static void SetBroadcastedAOOToHook(CNWSCreature*, BOOL);
static void PlayBattleMusicHook(CNWSAmbientSound*, BOOL);

static bool s_InBroadcastAttackOfOpportunity;
static bool s_SkipPushAndSignalCombatAttackOfOpportunityBefore;
Expand Down Expand Up @@ -86,6 +90,11 @@ void CombatEvents()
&CNWSCreature::SetBroadcastedAOOTo,
(void*)&SetBroadcastedAOOToHook, Hooks::Order::Early);
});
InitOnFirstSubscribe("NWNX_ON_AREA_PLAY_BATTLE_MUSIC_.*", []() {
s_PlayBattleMusicHook = Hooks::HookFunction(
API::Functions::_ZN16CNWSAmbientSound15PlayBattleMusicEi,
(void*)PlayBattleMusicHook, Hooks::Order::Early);
});
}

void StartCombatRoundHook(CNWSCombatRound* thisPtr, ObjectID oidTarget)
Expand Down Expand Up @@ -231,7 +240,7 @@ BOOL PushAndSignalCombatAttackOfOpportunityBefore(ObjectID oidSelf, ObjectID oid
return s_OnCombatAttackOfOpportunityResult;
}
s_SkipPushAndSignalCombatAttackOfOpportunityBefore = true;

auto PushAndSignal = [&](const std::string& ev) -> bool {
PushEventData("TARGET_OBJECT_ID", Utils::ObjectIDToString(oidTarget));
return SignalEvent(ev, oidSelf);
Expand Down Expand Up @@ -275,8 +284,30 @@ void SetBroadcastedAOOToHook(CNWSCreature *thisPtr, BOOL bValue)
return;
}
}

s_SetBroadcastedAOOToHook->CallOriginal<void>(thisPtr, bValue);
}

void PlayBattleMusicHook(CNWSAmbientSound *pThis, BOOL bPlay)
{
auto PushAndSignal = [&](const std::string& ev) -> bool {
PushEventData("PLAY", std::to_string(bPlay));
return SignalEvent(ev, pThis->m_nArea);
};

if ((pThis->m_bBattlePlaying && !bPlay) || (!pThis->m_bBattlePlaying && bPlay))
{
if (PushAndSignal("NWNX_ON_AREA_PLAY_BATTLE_MUSIC_BEFORE"))
{
s_PlayBattleMusicHook->CallOriginal<void>(pThis, bPlay);
}

PushAndSignal("NWNX_ON_AREA_PLAY_BATTLE_MUSIC_AFTER");
}
else
{
s_PlayBattleMusicHook->CallOriginal<void>(pThis, bPlay);
}
}

}
56 changes: 34 additions & 22 deletions Plugins/Events/NWScript/nwnx_events.nss
Original file line number Diff line number Diff line change
Expand Up @@ -1567,15 +1567,15 @@ _______________________________________
```
@warning Toggling the Whitelist to be off for this event will degrade performance.
_______________________________________
## Object Use Events (Placeables)
- NWNX_ON_OBJECT_USE_BEFORE
- NWNX_ON_OBJECT_USE_AFTER
## Object Use Events (Placeables)
- NWNX_ON_OBJECT_USE_BEFORE
- NWNX_ON_OBJECT_USE_AFTER

`OBJECT_SELF` = The player using the object
`OBJECT_SELF` = The player using the object

Event Data Tag | Type | Notes
----------------------|--------|-------
OBJECT | object | The Object being used |
Event Data Tag | Type | Notes
----------------------|--------|-------
OBJECT | object | The Object being used |
_______________________________________
## Broadcast Safe Projectile Events
- NWNX_ON_BROADCAST_SAFE_PROJECTILE_BEFORE
Expand All @@ -1602,28 +1602,38 @@ _______________________________________
\endcode
`TARGET_OBJECT_ID` will be `OBJECT_INVALID` if the projectile is cast at a location
_______________________________________
## Broadcast Attack of Opportunity Events
- NWNX_ON_BROADCAST_ATTACK_OF_OPPORTUNITY_BEFORE
- NWNX_ON_BROADCAST_ATTACK_OF_OPPORTUNITY_AFTER
## Broadcast Attack of Opportunity Events
- NWNX_ON_BROADCAST_ATTACK_OF_OPPORTUNITY_BEFORE
- NWNX_ON_BROADCAST_ATTACK_OF_OPPORTUNITY_AFTER

`OBJECT_SELF` = The creature broadcasting the Attack of Opportunity event
`OBJECT_SELF` = The creature broadcasting the Attack of Opportunity event

Event Data Tag | Type | Notes
----------------------|--------|-------
TARGET_OBJECT_ID | object | A single object the attack of opportunity is being broadcast to. Convert to object with StringToObject() |
Event Data Tag | Type | Notes
----------------------|--------|-------
TARGET_OBJECT_ID | object | A single object the attack of opportunity is being broadcast to. Convert to object with StringToObject() |
MOVEMENT | int | Whether this attack of opportunity is being triggered from movement |
_______________________________________
## Combat Attack of Opportunity Events
- NWNX_ON_COMBAT_ATTACK_OF_OPPORTUNITY_BEFORE
- NWNX_ON_COMBAT_ATTACK_OF_OPPORTUNITY_AFTER
## Combat Attack of Opportunity Events
- NWNX_ON_COMBAT_ATTACK_OF_OPPORTUNITY_BEFORE
- NWNX_ON_COMBAT_ATTACK_OF_OPPORTUNITY_AFTER

`OBJECT_SELF` = The creature performing the Attack of Opportunity against the broadcasting target.
`OBJECT_SELF` = The creature performing the Attack of Opportunity against the broadcasting target.

Event Data Tag | Type | Notes
----------------------|--------|-------
TARGET_OBJECT_ID | object | The target of the attack of opportunity. Convert to object with StringToObject() |
Event Data Tag | Type | Notes
----------------------|--------|-------
TARGET_OBJECT_ID | object | The target of the attack of opportunity. Convert to object with StringToObject() |

@note If the BEFORE event is skipped the broadcasting creature will still make a tumble skill roll if moving.
_______________________________________
## Area Play Battle Music Events
- NWNX_ON_AREA_PLAY_BATTLE_MUSIC_BEFORE
- NWNX_ON_AREA_PLAY_BATTLE_MUSIC_AFTER

`OBJECT_SELF` = The area playing or stopping the battle music.

Event Data Tag | Type | Notes
----------------------|--------|-------
PLAY | int | TRUE if the area is starting to play battle music, FALSE if stopping. |
_______________________________________
*/

Expand Down Expand Up @@ -1957,6 +1967,8 @@ const string NWNX_ON_BROADCAST_ATTACK_OF_OPPORTUNITY_BEFORE = "NWNX_ON_BROADCAST
const string NWNX_ON_BROADCAST_ATTACK_OF_OPPORTUNITY_AFTER = "NWNX_ON_BROADCAST_ATTACK_OF_OPPORTUNITY_AFTER";
const string NWNX_ON_COMBAT_ATTACK_OF_OPPORTUNITY_BEFORE = "NWNX_ON_COMBAT_ATTACK_OF_OPPORTUNITY_BEFORE";
const string NWNX_ON_COMBAT_ATTACK_OF_OPPORTUNITY_AFTER = "NWNX_ON_COMBAT_ATTACK_OF_OPPORTUNITY_AFTER";
const string NWNX_ON_AREA_PLAY_BATTLE_MUSIC_BEFORE = "NWNX_ON_AREA_PLAY_BATTLE_MUSIC_BEFORE";
const string NWNX_ON_AREA_PLAY_BATTLE_MUSIC_AFTER = "NWNX_ON_AREA_PLAY_BATTLE_MUSIC_AFTER";
/// @}

/// @name Events ObjectType Constants
Expand Down Expand Up @@ -2006,7 +2018,7 @@ const int NWNX_EVENTS_BROADCAST_SAFE_PROJECTILE_TYPE_WEAPON_VFX_SONIC = 5;
const int NWNX_EVENTS_BROADCAST_SAFE_PROJECTILE_TYPE_SPELL_DEFAULT = 6;
const int NWNX_EVENTS_BROADCAST_SAFE_PROJECTILE_TYPE_SPELL_USE_PATH = 7;
/// @}

/// @brief Scripts can subscribe to events.
///
/// Some events are dispatched via the NWNX plugin (see NWNX_EVENTS_EVENT_* constants).
Expand Down