📄 trigger.cpp
字号:
if (m_bActive && m_bTouchActivate && ValidateSender(hObj))
{
m_hLastSender = hObj;
// If this is a counter trigger, determine if we can activate or not...
if (++m_nCurrentActivation < m_nActivationCount)
{
return;
}
else
{
m_nCurrentActivation = 0;
}
PlayActivationSound();
// Make us wait a bit before we can be triggered again...
if (m_fMaxTriggerMessageDelay)
{
m_fDelayStartTime = g_pServerDE->GetTime();
g_pServerDE->SetNextUpdate(m_hObject, 0.01f);
for (int i = 0; i < MAX_TRIGGER_MESSAGES; i++)
{
if (m_fTriggerMessageDelay[i])
m_bDelay[i] = DTRUE;
else if (m_hstrTargetName[i] && m_hstrMessageName[i]) // Else send the message now
SendMessage(i);
}
// m_bDelay = DTRUE;
}
else
{
SendMessages();
g_pServerDE->SetNextUpdate(m_hObject, m_fTriggerResetTime);
}
m_bActive = DFALSE;
}
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: Trigger::InitialUpdate
//
// PURPOSE: Initial update
//
// ----------------------------------------------------------------------- //
DBOOL Trigger::InitialUpdate(DVector *position)
{
if (!g_pServerDE) return DFALSE;
g_pServerDE->SetObjectDims(m_hObject, &m_vDims);
g_pServerDE->SetObjectFlags(m_hObject, FLAG_TOUCH_NOTIFY);
// My object touch notification will trigger new updates
// until then, I don't care...
// Mark this object as savable
DDWORD dwFlags = g_pServerDE->GetObjectUserFlags(m_hObject);
dwFlags |= USRFLG_SAVEABLE;
g_pServerDE->SetObjectUserFlags(m_hObject, dwFlags);
g_pServerDE->SetNextUpdate(m_hObject, 0.0f);
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: Trigger::Update
//
// PURPOSE: Handle Update
//
// ----------------------------------------------------------------------- //
DBOOL Trigger::Update(DVector *position)
{
if (!g_pServerDE) return DFALSE;
DBOOL bDelayed = DFALSE;
// Trigger was delayed, send now
for (int i=0; i < MAX_TRIGGER_MESSAGES; i++)
{
if (m_bDelay[i])
{
bDelayed = DTRUE;
}
}
// Not waiting for any more delays, reset the trigger
if (!bDelayed)
{
m_bActive = DTRUE;
// My object touch notification will trigger new updates
// until then, I don't care.
g_pServerDE->SetNextUpdate(m_hObject, 0.0f);
return DTRUE;
}
else
{
DFLOAT fTime = g_pServerDE->GetTime();
bDelayed = DFALSE;
for (int i=0; i < MAX_TRIGGER_MESSAGES; i++)
{
if (m_bDelay[i])
{
if (fTime >= m_fDelayStartTime + m_fTriggerMessageDelay[i])
{
SendMessage(i);
m_bDelay[i] = DFALSE;
}
else
bDelayed = DTRUE; // Keep track of messages not sent, for NextUpdate
}
}
if (bDelayed)
{
g_pServerDE->SetNextUpdate(m_hObject, 0.01f);
}
else // No more messages, start reset time
{
g_pServerDE->SetNextUpdate(m_hObject, m_fTriggerResetTime);
}
}
return DTRUE;
}
// ------------------------------------------------------------ //
//
// ROUTINE: Trigger::EngineMessageFn
//
// PURPOSE: Handle engine messages
//
// ----------------------------------------------------------------------- //
DDWORD Trigger::EngineMessageFn(DDWORD messageID, void *pData, float fData)
{
switch(messageID)
{
case MID_UPDATE:
{
if (!Update((DVector *)pData))
{
g_pServerDE->RemoveObject(m_hObject);
return DFALSE;
}
break;
}
case MID_TOUCHNOTIFY:
{
ObjectTouch((HOBJECT)pData);
break;
}
case MID_PRECREATE:
{
if (fData == PRECREATE_WORLDFILE || fData == PRECREATE_STRINGPROP)
{
ReadProp((ObjectCreateStruct*)pData);
}
break;
}
case MID_INITIALUPDATE:
{
if (fData != INITIALUPDATE_SAVEGAME)
InitialUpdate((DVector *)pData);
break;
}
case MID_SAVEOBJECT:
Save((HMESSAGEWRITE)pData, (DDWORD)fData);
break;
case MID_LOADOBJECT:
Load((HMESSAGEREAD)pData, (DDWORD)fData);
break;
default : break;
}
return B2BaseClass::EngineMessageFn(messageID, pData, fData);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: Trigger::ObjectMessageFn
//
// PURPOSE: Handle object messages
//
// ----------------------------------------------------------------------- //
DDWORD Trigger::ObjectMessageFn(HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead)
{
switch (messageID)
{
case MID_TRIGGER :
{
HandleTriggerMsg(hSender, hRead);
}
break;
case MID_KEYQUERYRESPONSE:
{
HandleKeyQueryResponse(hSender, hRead);
}
break;
}
return B2BaseClass::ObjectMessageFn(hSender, messageID, hRead);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: Trigger::HandleKeyQueryResponse
//
// PURPOSE: Handle the MID_KEYQUERYRESPONSE message
//
// ----------------------------------------------------------------------- //
void Trigger::HandleKeyQueryResponse(HOBJECT hSender, HMESSAGEREAD hRead)
{
CServerDE* pServerDE = GetServerDE();
if (!pServerDE) return;
HSTRING hItemName = g_pServerDE->ReadFromMessageHString(hRead);
DBOOL bHaveItem = (DBOOL)g_pServerDE->ReadFromMessageByte(hRead);
// Check the key & locked status
if (m_bLocked && bHaveItem && g_pServerDE->CompareStringsUpper(hItemName, m_hstrKeyName))
{
pServerDE->FreeString(hItemName);
// unlock if necessary and send access granted or denied messages
m_bLocked = DFALSE;
if (m_hstrUnlockedMsg)
{
// send text message
}
/*
if (m_hstrUnlockedSound)
{
char *pSound = pServerDE->GetStringData(m_hstrUnlockedSound);
if (!pSound) return;
PlaySoundFromObject(hSender, pSound, 200.0f, SOUNDTYPE_MISC, SOUNDPRIORITY_HIGH);
}
*/
}
else
{
pServerDE->FreeString(hItemName);
if (m_hstrLockedMsg)
{
// send text message
}
}
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: Trigger::HandleTriggerMsg
//
// PURPOSE: Handle object messages
//
// ----------------------------------------------------------------------- //
void Trigger::HandleTriggerMsg(HOBJECT hSender, HMESSAGEREAD hRead)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_bActive) return;
HSTRING hMsg = pServerDE->ReadFromMessageHString(hRead);
char *pMsg = pServerDE->GetStringData(hMsg);
if (pMsg)
{
if (_mbsicmp((const unsigned char*)pMsg, (const unsigned char*)g_szTrigger) == 0 && ValidateSender(hSender))
{
// If this is a counter trigger, determine if we can activate or not...
if (++m_nCurrentActivation < m_nActivationCount)
{
pServerDE->FreeString(hMsg);
return;
}
else
{
m_nCurrentActivation = 0;
}
PlayActivationSound();
m_hLastSender = hSender;
if (m_fMaxTriggerMessageDelay)
{
m_fDelayStartTime = g_pServerDE->GetTime();
g_pServerDE->SetNextUpdate(m_hObject, 0.01f);
for (int i = 0; i < MAX_TRIGGER_MESSAGES; i++)
{
if (m_fTriggerMessageDelay[i])
m_bDelay[i] = DTRUE;
else if (m_hstrTargetName[i] && m_hstrMessageName[i]) // Else send the message now
SendMessage(i);
}
}
else
{
SendMessages();
g_pServerDE->SetNextUpdate(m_hObject, m_fTriggerResetTime);
}
m_bActive = DFALSE;
}
// reset the trigger: Set active, and clear the next update if any
else if (_mbsicmp((const unsigned char*)pMsg, (const unsigned char*)g_szReset) == 0)
{
m_bActive = DTRUE;
g_pServerDE->SetNextUpdate(m_hObject, 0.0f);
}
else if (_mbsicmp((const unsigned char*)pMsg, (const unsigned char*)g_szLock) == 0)
{
m_bLocked = DTRUE;
g_pServerDE->SetNextUpdate(m_hObject, 0.0f);
}
else if (_mbsicmp((const unsigned char*)pMsg, (const unsigned char*)g_szUnLock) == 0)
{
if (m_hstrUnlockedSound && m_bLocked)
{
char *pSound = pServerDE->GetStringData(m_hstrUnlockedSound);
if (!pSound)
{
g_pServerDE->FreeString( hMsg );
return;
}
if (GetGameType() == GAMETYPE_ACTION && g_pPlayerObj)
{
HSTRING hstr = g_pServerDE->FormatString(IDS_GENERAL_UNLOCKED);
g_pPlayerObj->SendConsoleMessage(g_pServerDE->GetStringData(hstr));
g_pServerDE->FreeString(hstr);
// g_pPlayerObj->SendConsoleMessage("Unlocked!");
}
else
{
PlaySoundFromObject(hSender, pSound, 200.0f, SOUNDPRIORITY_MISC_HIGH);
}
}
m_bLocked = DFALSE;
g_pServerDE->SetNextUpdate(m_hObject, 0.0f);
}
}
pServerDE->FreeString(hMsg);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: Trigger::SendMessage
//
// PURPOSE: Sends the trigger message for slot nSlot
//
// ----------------------------------------------------------------------- //
void Trigger::SendMessage(int nSlot)
{
if (m_hstrTargetName[nSlot] && m_hstrMessageName[nSlot])
{
SendTriggerMsgToObjects(this, m_hstrTargetName[nSlot], m_hstrMessageName[nSlot]);
}
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: Trigger::SendMessages
//
// PURPOSE: Sends the trigger messages
//
// ----------------------------------------------------------------------- //
void Trigger::SendMessages()
{
if (m_bSending) return;
m_bSending = DTRUE;
for (int i=0; i < MAX_TRIGGER_MESSAGES; i++)
{
if (m_hstrTargetName[i] && m_hstrMessageName[i])
{
SendTriggerMsgToObjects(this, m_hstrTargetName[i], m_hstrMessageName[i]);
}
}
m_bSending = DFALSE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: Trigger::PlayActivationSound
//
// PURPOSE: Plays the activation sound, if any
//
// ----------------------------------------------------------------------- //
void Trigger::PlayActivationSound()
{
if (!m_hstrActivationSound || !g_pServerDE) return;
char* pSound = g_pServerDE->GetStringData(m_hstrActivationSound);
if (pSound && pSound[0] != '\0')
{
PlaySoundFromObject(m_hObject, pSound, m_fSoundRadius, SOUNDPRIORITY_MISC_MEDIUM);
}
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: Trigger::ValidateSender
//
// PURPOSE: Determines if the object triggering us is allowed to.
//
// ----------------------------------------------------------------------- //
DBOOL Trigger::ValidateSender(HOBJECT hObj)
{
DBOOL bRetVal = DFALSE;
HCLASS hAIObj = g_pServerDE->GetClass("CBaseCharacter");
HCLASS hPlayerObj = g_pServerDE->GetClass("CPlayerObj");
HCLASS hTriggerObj = g_pServerDE->GetClass("Trigger");
HCLASS hObjClass = g_pServerDE->GetObjectClass(hObj);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -