Skip to content

Commit 39a23b4

Browse files
authored
Merge pull request #1634 from summonFox/Events-BroadcastSafeProjectile
Events: add `NWNX_ON_BROADCAST_SAFE_PROJECTILE_{BEFORE|AFTER}`
2 parents b5cd567 + a3f9fe2 commit 39a23b4

File tree

3 files changed

+80
-0
lines changed

3 files changed

+80
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
88
https://github.com/nwnxee/unified/compare/build8193.35.37...HEAD
99

1010
### Added
11+
- Events: added skippable event `NWNX_ON_BROADCAST_SAFE_PROJECTILE_{BEFORE|AFTER}` which fires whenever a projectile VFX is created for ranged weapons and spells.
1112
- Events: added skippable event `NWNX_ON_BROADCAST_ATTACK_OF_OPPORTUNITY_{BEFORE|AFTER}` which allows skipping a creature provoking attacks of opportunities from enemies.
1213
- 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.
1314

Plugins/Events/Events/ObjectEvents.cpp

+37
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ using namespace NWNXLib::API::Constants;
1010
static NWNXLib::Hooks::Hook s_AddLockObjectActionHook;
1111
static NWNXLib::Hooks::Hook s_AddUnlockObjectActionHook;
1212
static NWNXLib::Hooks::Hook s_AddUseObjectActionHook;
13+
static NWNXLib::Hooks::Hook s_BroadcastSafeProjectileHook;
1314

1415
static int32_t AddLockObjectActionHook(CNWSObject*, ObjectID);
1516
static int32_t AddUnlockObjectActionHook(CNWSObject*, ObjectID, ObjectID, int32_t);
1617
static int32_t AddUseObjectActionHook(CNWSObject*, ObjectID);
18+
static void BroadcastSafeProjectileHook(CNWSObject*, ObjectID, ObjectID, Vector, Vector, uint32_t, uint8_t, uint32_t, uint8_t, uint8_t);
1719

1820
void ObjectEvents() __attribute__((constructor));
1921
void ObjectEvents()
@@ -32,6 +34,11 @@ void ObjectEvents()
3234
s_AddUseObjectActionHook = Hooks::HookFunction(&CNWSObject::AddUseObjectAction,
3335
(void*)&AddUseObjectActionHook, Hooks::Order::Early);
3436
});
37+
38+
InitOnFirstSubscribe("NWNX_ON_BROADCAST_SAFE_PROJECTILE_.*", []() {
39+
s_BroadcastSafeProjectileHook = Hooks::HookFunction(&CNWSObject::BroadcastSafeProjectile,
40+
(void*)&BroadcastSafeProjectileHook, Hooks::Order::Early);
41+
});
3542
}
3643

3744
int32_t AddLockObjectActionHook(CNWSObject *thisPtr, ObjectID oidDoor)
@@ -110,4 +117,34 @@ int32_t AddUseObjectActionHook(CNWSObject *thisPtr, ObjectID oidObjectToUse)
110117
return retVal;
111118
}
112119

120+
void BroadcastSafeProjectileHook(CNWSObject *thisPtr, ObjectID oidOriginator, ObjectID oidTarget, Vector vOriginator, Vector vTarget, uint32_t nDelta,
121+
uint8_t nProjectileType, uint32_t nSpellID, uint8_t nAttackResult, uint8_t nProjectilePathType)
122+
{
123+
if (!IsIDInWhitelist("NWNX_ON_BROADCAST_SAFE_PROJECTILE_TYPE", nProjectileType) || !IsIDInWhitelist("NWNX_ON_BROADCAST_SAFE_PROJECTILE_SPELL_ID", nSpellID))
124+
{
125+
s_BroadcastSafeProjectileHook->CallOriginal<void>(thisPtr, oidOriginator, oidTarget, vOriginator, vTarget, nDelta, nProjectileType, nSpellID, nAttackResult, nProjectilePathType);
126+
return;
127+
}
128+
129+
auto PushAndSignal = [&](const std::string& ev) -> bool {
130+
PushEventData("TARGET_OBJECT_ID", Utils::ObjectIDToString(oidTarget));
131+
PushEventData("TARGET_POSITION_X", std::to_string(vTarget.x));
132+
PushEventData("TARGET_POSITION_Y", std::to_string(vTarget.y));
133+
PushEventData("TARGET_POSITION_Z", std::to_string(vTarget.z));
134+
PushEventData("DELTA", std::to_string(nDelta));
135+
PushEventData("PROJECTILE_TYPE", std::to_string(nProjectileType));
136+
PushEventData("SPELL_ID", std::to_string(nSpellID));
137+
PushEventData("ATTACK_RESULT", std::to_string(nAttackResult));
138+
PushEventData("PROJECTILE_PATH_TYPE", std::to_string(nProjectilePathType));
139+
return SignalEvent(ev, thisPtr->m_idSelf);
140+
};
141+
142+
if (PushAndSignal("NWNX_ON_BROADCAST_SAFE_PROJECTILE_BEFORE"))
143+
{
144+
s_BroadcastSafeProjectileHook->CallOriginal<void>(thisPtr, oidOriginator, oidTarget, vOriginator, vTarget, nDelta, nProjectileType, nSpellID, nAttackResult, nProjectilePathType);
145+
}
146+
147+
PushAndSignal("NWNX_ON_BROADCAST_SAFE_PROJECTILE_AFTER");
148+
}
149+
113150
}

Plugins/Events/NWScript/nwnx_events.nss

+42
Original file line numberDiff line numberDiff line change
@@ -1559,6 +1559,31 @@ _______________________________________
15591559
Event Data Tag | Type | Notes
15601560
----------------------|--------|-------
15611561
OBJECT | object | The Object being used |
1562+
_______________________________________
1563+
## Broadcast Safe Projectile Events
1564+
- NWNX_ON_BROADCAST_SAFE_PROJECTILE_BEFORE
1565+
- NWNX_ON_BROADCAST_SAFE_PROJECTILE_AFTER
1566+
1567+
`OBJECT_SELF` = The creature casting the spell
1568+
1569+
Event Data Tag | Type | Notes |
1570+
----------------------|--------|-------|
1571+
TARGET_OBJECT_ID | string | Convert to object with StringToObject() |
1572+
TARGET_POSITION_X | float | |
1573+
TARGET_POSITION_Y | float | |
1574+
TARGET_POSITION_Z | float | |
1575+
DELTA | int | Time in milliseconds before the projectile reaches its destination |
1576+
PROJECTILE_TYPE | int | @ref events_projtype "NWNX_EVENTS_BROADCAST_SAFE_PROJECTILE_TYPE_*" |
1577+
SPELL_ID | int | |
1578+
ATTACK_RESULT | int | 0=n/a, 1=hit, 2=parried, 3=critical hit, 4=miss, 5=resisted, 7=automatic hit, 8=concealed, 9=miss chance, 10=devastating crit |
1579+
PROJECTILE_PATH_TYPE | int | @nwn{Projectile_path_type,PROJECTILE_PATH_TYPE_*} |
1580+
1581+
@note This event fires for all projectiles. It's recommended to use ID whitelists with this event. You can whitelist the event by the projectile type, spell id, or both:
1582+
\code{.c}
1583+
NWNX_Events_AddIDToWhitelist("NWNX_ON_BROADCAST_SAFE_PROJECTILE_TYPE", NWNX_EVENTS_BROADCAST_SAFE_PROJECTILE_TYPE_*);
1584+
NWNX_Events_AddIDToWhitelist("NWNX_ON_BROADCAST_SAFE_PROJECTILE_SPELL", SPELL_*);
1585+
\endcode
1586+
`TARGET_OBJECT_ID` will be `OBJECT_INVALID` if the projectile is cast at a location
15621587
_______________________________________
15631588
## Broadcast Attack of Opportunity Events
15641589
- NWNX_ON_BROADCAST_ATTACK_OF_OPPORTUNITY_BEFORE
@@ -1907,6 +1932,8 @@ const string NWNX_ON_RUN_EVENT_SCRIPT_BEFORE = "NWNX_ON_RUN_EVENT_SCRIPT_BEFORE"
19071932
const string NWNX_ON_RUN_EVENT_SCRIPT_AFTER = "NWNX_ON_RUN_EVENT_SCRIPT_AFTER";
19081933
const string NWNX_ON_OBJECT_USE_BEFORE = "NWNX_ON_OBJECT_USE_BEFORE";
19091934
const string NWNX_ON_OBJECT_USE_AFTER = "NWNX_ON_OBJECT_USE_AFTER";
1935+
const string NWNX_ON_BROADCAST_SAFE_PROJECTILE_BEFORE = "NWNX_ON_BROADCAST_SAFE_PROJECTILE_BEFORE";
1936+
const string NWNX_ON_BROADCAST_SAFE_PROJECTILE_AFTER = "NWNX_ON_BROADCAST_SAFE_PROJECTILE_AFTER";
19101937
const string NWNX_ON_BROADCAST_ATTACK_OF_OPPORTUNITY_BEFORE = "NWNX_ON_BROADCAST_ATTACK_OF_OPPORTUNITY_BEFORE";
19111938
const string NWNX_ON_BROADCAST_ATTACK_OF_OPPORTUNITY_AFTER = "NWNX_ON_BROADCAST_ATTACK_OF_OPPORTUNITY_AFTER";
19121939
const string NWNX_ON_COMBAT_ATTACK_OF_OPPORTUNITY_BEFORE = "NWNX_ON_COMBAT_ATTACK_OF_OPPORTUNITY_BEFORE";
@@ -1948,6 +1975,19 @@ const int NWNX_EVENTS_DM_SET_VARIABLE_TYPE_STRING = 2;
19481975
const int NWNX_EVENTS_DM_SET_VARIABLE_TYPE_OBJECT = 3;
19491976
/// @}
19501977

1978+
/// @name Events BroadcastSafeProjectile Constants
1979+
/// @anchor events_projtype
1980+
/// @{
1981+
const int NWNX_EVENTS_BROADCAST_SAFE_PROJECTILE_TYPE_WEAPON_VFX_NONE = 0;
1982+
const int NWNX_EVENTS_BROADCAST_SAFE_PROJECTILE_TYPE_WEAPON_VFX_ACID = 1;
1983+
const int NWNX_EVENTS_BROADCAST_SAFE_PROJECTILE_TYPE_WEAPON_VFX_COLD = 2;
1984+
const int NWNX_EVENTS_BROADCAST_SAFE_PROJECTILE_TYPE_WEAPON_VFX_ELECTRICAL = 3;
1985+
const int NWNX_EVENTS_BROADCAST_SAFE_PROJECTILE_TYPE_WEAPON_VFX_FIRE = 4;
1986+
const int NWNX_EVENTS_BROADCAST_SAFE_PROJECTILE_TYPE_WEAPON_VFX_SONIC = 5;
1987+
const int NWNX_EVENTS_BROADCAST_SAFE_PROJECTILE_TYPE_SPELL_DEFAULT = 6;
1988+
const int NWNX_EVENTS_BROADCAST_SAFE_PROJECTILE_TYPE_SPELL_USE_PATH = 7;
1989+
/// @}
1990+
19511991
/// @brief Scripts can subscribe to events.
19521992
///
19531993
/// Some events are dispatched via the NWNX plugin (see NWNX_EVENTS_EVENT_* constants).
@@ -2040,6 +2080,7 @@ string NWNX_Events_GetEventData(string tag);
20402080
/// - Decrement Spell Count event
20412081
/// - Play Visual Effect event
20422082
/// - EventScript event
2083+
/// - Broadcast Safe Projectile event
20432084
/// - Attack of Opportunity events
20442085
void NWNX_Events_SkipEvent();
20452086

@@ -2084,6 +2125,7 @@ void NWNX_Events_RemoveObjectFromDispatchList(string sEvent, string sScriptOrChu
20842125
/// - NWNX_ON_CAST_SPELL -> SpellID
20852126
/// - NWNX_ON_HAS_FEAT -> FeatID (default enabled)
20862127
/// - NWNX_ON_RUN_EVENT_SCRIPT -> EVENT_SCRIPT_* (default enabled)
2128+
/// - NWNX_ON_BROADCAST_SAFE_PROJECTILE -> NWNX_ON_BROADCAST_SAFE_PROJECTILE_TYPE for ProjectileType, NWNX_ON_BROADCAST_SAFE_PROJECTILE_SPELL for SpellID
20872129
///
20882130
/// @note This enables the whitelist for ALL scripts subscribed to sEvent.
20892131
/// @param sEvent The event name without _BEFORE / _AFTER.

0 commit comments

Comments
 (0)