ff_u_plc_examine
Prevent examine action if too far away.
The examine panels are disabled for every player on client enter, and never
enabled again, so the engine never opens one by itself. When a player tries to
examine an object, the unit checks it, then opens the panel with
ActionExamine, which works even with the panel disabled.
Items in the player’s own inventory can always be examined. For other objects, the distance is measured to the object, or to the container holding it. A book can only be read from the player’s own inventory.
When an examine is refused, the player gets a floating text instead: the object
is too far away, the book must be in the inventory, or, for an object whose
EXAMINE flag is "N", there is nothing special about it.
Variables
ENABLE__FF_U_PLC_EXAMINE: (string) (opt-in) Set to "Y" on the module to
enable the unit.
EXAMINE_DISTANCE: (int) Maximum examine distance, in metres. Read on the
object, then its area, then the module. Defaults to 8.
EXAMINE: (string) Set to "N" to hide the description. Read on the
object, then its area, then the module. Defaults to "Y".
Source code
// @code
#include "ff_i_core"
const string ENABLE__FF_U_PLC_EXAMINE = "ENABLE__FF_U_PLC_EXAMINE";
const string EXAMINE_DISTANCE = "EXAMINE_DISTANCE";
const string EXAMINE = "EXAMINE";
const int DEFAULT_EXAMINE_DISTANCE = 8; // Metres
// -----------------------------------------------------------------------------
//! @brief The object the distance is measured to: the container of an item, or the object itself.
//! @param oObject The examined object.
object GetExamineTarget(object oObject);
object GetExamineTarget(object oObject)
{
object oOwner = GetItemPossessor(oObject);
if (GetIsObjectValid(oOwner))
return oOwner;
return oObject;
}
// -----------------------------------------------------------------------------
//! @brief Return TRUE if oPC can examine oObject, or send the reason to oPC.
//! @param oPC The player.
//! @param oObject The examined object.
int IsEligible(object oPC, object oObject);
int IsEligible(object oPC, object oObject)
{
// Anything the player carries is close enough, and a book is readable.
if (GetItemPossessor(oObject) == oPC)
return TRUE;
// A book must be read from the player's own inventory.
if (GetBaseItemType(oObject) == BASE_ITEM_BOOK)
{
FloatingTextStringOnCreature("You can only read a book if it's in your inventory", oPC, FALSE, FALSE);
return FALSE;
}
int nMaxDistance = GetRecursiveInt(oObject, EXAMINE_DISTANCE, DEFAULT_EXAMINE_DISTANCE);
float fDistance = GetDistanceBetween(oPC, GetExamineTarget(oObject));
if (fDistance <= 0.0f || fDistance > IntToFloat(nMaxDistance))
{
FloatingTextStringOnCreature("Object is too far away to be examined", oPC, FALSE, FALSE);
return FALSE;
}
if (!GetRecursiveObjectFlag(oObject, EXAMINE, TRUE))
{
FloatingTextStringOnCreature("There is nothing special about this object", oPC, FALSE, FALSE);
return FALSE;
}
return TRUE;
}
// -----------------------------------------------------------------------------
//! @brief Disable every examine panel, so the engine never opens one by itself.
//! The panels are never enabled again.
//! @param oPC The player.
void DisableExaminePanels(object oPC);
void DisableExaminePanels(object oPC)
{
SetGuiPanelDisabled(oPC, GUI_PANEL_EXAMINE_DOOR, TRUE);
SetGuiPanelDisabled(oPC, GUI_PANEL_EXAMINE_CREATURE, TRUE);
SetGuiPanelDisabled(oPC, GUI_PANEL_EXAMINE_ITEM, TRUE);
SetGuiPanelDisabled(oPC, GUI_PANEL_EXAMINE_PLACEABLE, TRUE);
}
// -----------------------------------------------------------------------------
//! @brief Check an examine the engine refused because the panel is disabled, and
//! open the panel with ActionExamine if oPC can examine the object.
void OnGuiExamine();
void OnGuiExamine()
{
if (GetLastGuiEventType() != GUIEVENT_DISABLED_PANEL_ATTEMPT_OPEN)
return;
switch (GetLastGuiEventInteger())
{
case GUI_PANEL_EXAMINE_PLACEABLE:
case GUI_PANEL_EXAMINE_ITEM:
case GUI_PANEL_EXAMINE_DOOR:
case GUI_PANEL_EXAMINE_CREATURE:
break;
default:
return;
}
object oPC = GetLastGuiEventPlayer();
object oObject = GetLastGuiEventObject();
if (!GetIsPC(oPC) || !GetIsObjectValid(oObject))
return;
// ActionExamine opens the panel even though it is disabled
if (IsEligible(oPC, oObject))
AssignCommand(oPC, ActionExamine(oObject));
}
// -----------------------------------------------------------------------------
void main()
{
string sEvent = NWNX_Events_GetCurrentEvent();
if (sEvent == ON_REGISTER)
{
if (!GetModuleFlag(ENABLE__FF_U_PLC_EXAMINE, FALSE))
return;
SubscribeToEvent(ON_DEFAULT_CLIENT_ENTER, __FILE__);
SubscribeToEvent(ON_DEFAULT_PLAYER_GUIEVENT, __FILE__);
}
else if (sEvent == ON_DEFAULT_CLIENT_ENTER)
{
object oPC = GetEnteringObject();
if (GetIsPC(oPC))
DisableExaminePanels(oPC);
}
else if (sEvent == ON_DEFAULT_PLAYER_GUIEVENT)
OnGuiExamine();
}