2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-14 02:27:40 -04:00

Merge branch 'master' into ticket/10

This commit is contained in:
rarified
2021-07-09 16:13:26 -06:00
32 changed files with 603 additions and 459 deletions

View File

@ -49,8 +49,8 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../pnNetCommon/plNetApp.h"
#include "../plAvatar/plArmatureMod.h"
#include "../pnSceneObject/plSceneObject.h"
bool plVolumeSensorConditionalObject::makeBriceHappyVar = true;
#include "../pnMessage/plPlayerPageMsg.h"
#include "../../NucleusLib/inc/plgDispatch.h"
plObjectInBoxConditionalObject::plObjectInBoxConditionalObject() :
fCurrentTrigger(nil)
@ -129,12 +129,52 @@ fTrigNum(-1),
fType(0),
fFirst(false),
fTriggered(false),
fIgnoreExtraEnters(true)
fFlags(kIgnoreExtraEnters)
{
SetSatisfied(true);
}
void plVolumeSensorConditionalObject::IgnoreExtraEnters(bool ignore)
{
if (ignore)
fFlags |= kIgnoreExtraEnters;
else
fFlags &= ~kIgnoreExtraEnters;
}
void plVolumeSensorConditionalObject::NoServerArbitration(bool noArbitration)
{
if (noArbitration) {
plgDispatch::Dispatch()->RegisterForExactType(plPlayerPageMsg::Index(), GetKey());
fFlags |= kNoServerArbitration;
} else {
plgDispatch::Dispatch()->UnRegisterForExactType(plPlayerPageMsg::Index(), GetKey());
fFlags &= ~kNoServerArbitration;
}
}
bool plVolumeSensorConditionalObject::IIsLocal(const plKey& key) const
{
if (key == plNetClientApp::GetInstance()->GetLocalPlayerKey())
return true;
const plSceneObject* hitter = plSceneObject::ConvertNoRef(key->ObjectIsLoaded());
if (hitter) {
for (size_t i = 0; i < hitter->GetNumModifiers(); ++i) {
const plArmatureMod* am = plArmatureMod::ConvertNoRef(hitter->GetModifier(i));
if (am && !am->IsLocalAI())
return false;
}
if (hitter->IsLocallyOwned() != plSynchedObject::kYes)
return false;
}
// Yes, I know that we're saying YES for not loaded objects. This matches the previous behavior.
return true;
}
hsBool plVolumeSensorConditionalObject::MsgReceive(plMessage* msg)
{
plActivatorMsg* pActivateMsg = plActivatorMsg::ConvertNoRef(msg);
@ -144,55 +184,40 @@ hsBool plVolumeSensorConditionalObject::MsgReceive(plMessage* msg)
if (!fLogicMod->HasFlag(plLogicModBase::kRequestingTrigger))
fLogicMod->GetNotify()->ClearEvents();
// Track the hittee for the NoArbitration case so we can trigger the exit volume on link out
fHittee = pActivateMsg->fHiteeObj;
// Track the enters/exits on all clients
if (pActivateMsg->fTriggerType == plActivatorMsg::kVolumeEnter)
{
int i;
for (i = 0; i < fInside.Count(); i++)
{
if (fInside[i] == pActivateMsg->fHitterObj)
{
if (fIgnoreExtraEnters)
return false; // this is the "correct" way to handle this situation
break; // this is for those special situations where, due to some physics oddity, we need to allow the avatar to enter without exiting
}
}
if (i == fInside.Count())
fInside.Append(pActivateMsg->fHitterObj);
if (makeBriceHappyVar)
{
plSceneObject *pObj = plSceneObject::ConvertNoRef( pActivateMsg->fHitterObj->ObjectIsLoaded() );
if( pObj )
{
//need to check for human vs quabish type things in here
int i;
for( i = 0; i < pObj->GetNumModifiers(); i++ )
{
if (plArmatureMod::ConvertNoRef( pObj->GetModifier(i)))
{
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != pActivateMsg->fHitterObj)
{
plArmatureMod *am=const_cast<plArmatureMod*>( plArmatureMod::ConvertNoRef(pObj->GetModifier(i)));
if((am->IsLocalAI())==nil)
{
return false;
}
}
}
}
plSynchedObject* syncObj = (plSynchedObject*)pObj;
if (syncObj->IsLocallyOwned() != plSynchedObject::kYes)
{
return false;
}
}
auto it = fInside.find(pActivateMsg->fHitterObj);
if (it != fInside.end() && fFlags & kIgnoreExtraEnters) {
// This is normally what we should do. You're already inside the region,
// so we don't care about a dupe enter. However, PhysX is weird, so sometimes
// we might want to allow dupe enters.
return false;
}
fInside.insert(pActivateMsg->fHitterObj);
// From here on out, we only care about local avatars
if (!IIsLocal(pActivateMsg->fHitterObj))
return false;
if (fType == kTypeEnter)
{
fLogicMod->GetNotify()->AddCollisionEvent(true, pActivateMsg->fHitterObj, pActivateMsg->fHiteeObj, false);
fLogicMod->RequestTrigger(false);
if ((fFlags & kNoServerArbitration))
{
if (Satisfied())
fLogicMod->Trigger(false);
}
else
{
fLogicMod->RequestTrigger(false);
}
}
else
if (fType == kTypeExit && !(fFlags & kNoServerArbitration))
{
fLogicMod->GetNotify()->AddCollisionEvent(false, pActivateMsg->fHitterObj, pActivateMsg->fHiteeObj, false);
fLogicMod->RequestUnTrigger();
@ -202,56 +227,54 @@ hsBool plVolumeSensorConditionalObject::MsgReceive(plMessage* msg)
else
if (pActivateMsg->fTriggerType == plActivatorMsg::kVolumeExit)
{
for (int i = 0; i < fInside.Count(); i++)
{
if (fInside[i] == pActivateMsg->fHitterObj)
auto it = fInside.find(pActivateMsg->fHitterObj);
if (it == fInside.end())
return false;
fInside.erase(it);
// From here on out, we only care about local avatars
if (!IIsLocal(pActivateMsg->fHitterObj))
return false;
if (fType == kTypeExit) {
fLogicMod->GetNotify()->AddCollisionEvent(false, pActivateMsg->fHitterObj, pActivateMsg->fHiteeObj, false);
if (fFlags & kNoServerArbitration)
{
fInside.Remove(i);
if (makeBriceHappyVar)
{
//need to check for human vs quabish type things in here
plSceneObject *pObj = plSceneObject::ConvertNoRef( pActivateMsg->fHitterObj->ObjectIsLoaded() );
if( pObj )
{
int i;
for( i = 0; i < pObj->GetNumModifiers(); i++ )
{
if (plArmatureMod::ConvertNoRef( pObj->GetModifier(i)))
{
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != pActivateMsg->fHitterObj)
{
plArmatureMod *am=const_cast<plArmatureMod*>( plArmatureMod::ConvertNoRef(pObj->GetModifier(i)));
if((am->IsLocalAI())==nil)
{
return false;
}
}
}
}
plSynchedObject* syncObj = (plSynchedObject*)pObj;
if (syncObj->IsLocallyOwned() != plSynchedObject::kYes)
{
return false;
}
}
}
if (fType == kTypeExit)
{
fLogicMod->GetNotify()->AddCollisionEvent(false, pActivateMsg->fHitterObj, pActivateMsg->fHiteeObj, false);
fLogicMod->RequestTrigger(false);
}
else
{
fLogicMod->GetNotify()->AddCollisionEvent(true, pActivateMsg->fHitterObj, pActivateMsg->fHiteeObj, false);
fLogicMod->RequestUnTrigger();
}
return false;
if (Satisfied())
fLogicMod->Trigger(false);
}
else
{
fLogicMod->RequestTrigger(false);
}
}
else if (fType == kTypeEnter && !(fFlags & kNoServerArbitration))
{
fLogicMod->GetNotify()->AddCollisionEvent(true, pActivateMsg->fHitterObj, pActivateMsg->fHiteeObj, false);
fLogicMod->RequestUnTrigger();
}
return true;
}
return true;
}
plPlayerPageMsg* page = plPlayerPageMsg::ConvertNoRef(msg);
if (page && page->fUnload) {
hsAssert(fFlags & kNoServerArbitration, "WTF -- should only get here if the VSCO skips arbitration!");
auto it = fInside.find(page->fPlayer);
if (it != fInside.end()) {
fInside.erase(it);
if (fHittee && fType == kTypeExit) {
const plSceneObject* hitteeSO = plSceneObject::ConvertNoRef(fHittee->ObjectIsLoaded());
if (hitteeSO && hitteeSO->IsLocallyOwned() == plSynchedObject::kYes) {
fLogicMod->GetNotify()->AddCollisionEvent(false, page->fPlayer, fHittee, false);
if (Satisfied())
fLogicMod->Trigger(false);
}
}
}
return false;
return true;
}
return plConditionalObject::MsgReceive(msg);
}
@ -260,20 +283,20 @@ hsBool plVolumeSensorConditionalObject::Satisfied()
{
if (fType == kTypeExit && fFirst && !fTriggered)
{
if (fInside.Count())
if (!fInside.empty())
fTriggered = true;
return true;
}
if (fTriggered)
{
if (fInside.Count() == 0)
if (fInside.empty())
fTriggered = false;
return false;
}
if (fTrigNum == -1)
return true;
if (fInside.Count() == fTrigNum)
if (fInside.size() == fTrigNum)
return true;
else
return false;
@ -293,156 +316,11 @@ void plVolumeSensorConditionalObject::Write(hsStream* stream, hsResMgr* mgr)
stream->WriteSwap32(fType);
stream->WriteBool(fFirst);
}
#include "../pnMessage/plPlayerPageMsg.h"
#include "../../NucleusLib/inc/plgDispatch.h"
hsBool plVolumeSensorConditionalObjectNoArbitration::MsgReceive(plMessage* msg)
{
plActivatorMsg* pActivateMsg = plActivatorMsg::ConvertNoRef(msg);
if (pActivateMsg)
{
// single player hack
if (!fLogicMod->HasFlag(plLogicModBase::kRequestingTrigger))
fLogicMod->GetNotify()->ClearEvents();
fHittee= pActivateMsg->fHiteeObj;
if (pActivateMsg->fTriggerType == plActivatorMsg::kVolumeEnter)
{
int i;
for (i = 0; i < fInside.Count(); i++)
{
if (fInside[i] == pActivateMsg->fHitterObj)
{
if (fIgnoreExtraEnters)
return false; // this is the "correct" way to handle this situation
break; // this is for those special situations where, due to some physics oddity, we need to allow the avatar to enter without exiting
}
}
if (i == fInside.Count())
fInside.Append(pActivateMsg->fHitterObj);
if (makeBriceHappyVar)
{
plSceneObject *pObj = plSceneObject::ConvertNoRef( pActivateMsg->fHitterObj->ObjectIsLoaded() );
if( pObj )
{
//need to check for human vs quabish type things in here
int i;
for( i = 0; i < pObj->GetNumModifiers(); i++ )
{
if (plArmatureMod::ConvertNoRef( pObj->GetModifier(i)))
{
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != pActivateMsg->fHitterObj)
{
plArmatureMod *am=const_cast<plArmatureMod*>( plArmatureMod::ConvertNoRef(pObj->GetModifier(i)));
if((am->IsLocalAI())==nil)
{
return false;
}
}
}
}
plSynchedObject* syncObj = (plSynchedObject*)pObj;
if (syncObj->IsLocallyOwned() != plSynchedObject::kYes)
{
return false;
}
}
}
if (fType == kTypeEnter)
{
fLogicMod->GetNotify()->AddCollisionEvent(true, pActivateMsg->fHitterObj, pActivateMsg->fHiteeObj, false);
//fLogicMod->RequestTrigger(false);
if (!Satisfied())
return false;
fLogicMod->Trigger(false);
}
return false;
}
else
if (pActivateMsg->fTriggerType == plActivatorMsg::kVolumeExit)
{
for (int i = 0; i < fInside.Count(); i++)
{
if (fInside[i] == pActivateMsg->fHitterObj)
{
fInside.Remove(i);
if (makeBriceHappyVar)
{
//need to check for human vs quabish type things in here
plSceneObject *pObj = plSceneObject::ConvertNoRef( pActivateMsg->fHitterObj->ObjectIsLoaded() );
if( pObj )
{
int i;
for( i = 0; i < pObj->GetNumModifiers(); i++ )
{
if (plArmatureMod::ConvertNoRef( pObj->GetModifier(i)))
{
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != pActivateMsg->fHitterObj)
{
plArmatureMod *am=const_cast<plArmatureMod*>( plArmatureMod::ConvertNoRef(pObj->GetModifier(i)));
if((am->IsLocalAI())==nil)
{
return false;
}
}
}
}
plSynchedObject* syncObj = (plSynchedObject*)pObj;
if (syncObj->IsLocallyOwned() != plSynchedObject::kYes)
{
return false;
}
}
}
if (fType == kTypeExit)
{
fLogicMod->GetNotify()->AddCollisionEvent(false, pActivateMsg->fHitterObj, pActivateMsg->fHiteeObj, false);
//fLogicMod->RequestTrigger(false);
if (!Satisfied())
return false;
fLogicMod->Trigger(false);
}
return false;
}
}
}
return false;
}
plPlayerPageMsg* page = plPlayerPageMsg::ConvertNoRef(msg);
if(page && page->fUnload)
{
for(int j= 0; j< fInside.Count(); j++)
{
if(fInside[j] == page->fPlayer)
{//this is the one inside
if(fHittee)
{
plSceneObject *so = plSceneObject::ConvertNoRef(fHittee->ObjectIsLoaded());
if(so && so->IsLocallyOwned())
{
if (fType == kTypeExit)
{
fLogicMod->GetNotify()->AddCollisionEvent(false, page->fPlayer, fHittee, false);
//fLogicMod->RequestTrigger(false);
if (!Satisfied())
return false;
fLogicMod->Trigger(false);
}
}
}
fInside.Remove(j);
}
}
}
return plConditionalObject::MsgReceive(msg);
}
void plVolumeSensorConditionalObjectNoArbitration::Read(hsStream* stream, hsResMgr* mgr)
{
plVolumeSensorConditionalObject::Read(stream, mgr);
plgDispatch::Dispatch()->RegisterForExactType(plPlayerPageMsg::Index(), GetKey());
}
// We must have a valid fpKey before we do this, hence why this is not in the constructor
NoServerArbitration(true);
}

View File

@ -43,8 +43,10 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#ifndef plObjectInBoxConditionalObject_inc
#define plObjectInBoxConditionalObject_inc
#include <stdint.h>
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
#include "hsTemplates.h"
#include <set>
class plKey;
@ -77,17 +79,26 @@ class plVolumeSensorConditionalObject : public plConditionalObject
protected:
hsTArray<plKey> fInside;
std::set<plKey> fInside;
int fTrigNum;
int fType;
hsBool fFirst;
hsBool fTriggered;
hsBool fIgnoreExtraEnters;
plKey fHittee;
uint32_t fFlags;
enum
{
/** */
kIgnoreExtraEnters = (1<<0),
kNoServerArbitration = (1<<1),
};
bool IIsLocal(const plKey& key) const;
public:
static bool makeBriceHappyVar;
enum
{
kTypeEnter = 1,
@ -99,33 +110,30 @@ public:
CLASSNAME_REGISTER( plVolumeSensorConditionalObject );
GETINTERFACE_ANY( plVolumeSensorConditionalObject, plConditionalObject );
virtual hsBool MsgReceive(plMessage* msg);
hsBool MsgReceive(plMessage* msg);
void Evaluate(){;}
void Evaluate() {}
void Reset() { SetSatisfied(false); }
virtual hsBool Satisfied();
hsBool Satisfied() HS_OVERRIDE;
void SetType(int i) { fType = i; }
void SetTrigNum(int i) { fTrigNum = i; }
void SetFirst(hsBool b) { fFirst = b; }
void IgnoreExtraEnters(hsBool ignore = true) {fIgnoreExtraEnters = ignore;}
void IgnoreExtraEnters(bool ignore = true);
void NoServerArbitration(bool noArbitration = true);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
void Read(hsStream* stream, hsResMgr* mgr) HS_OVERRIDE;
void Write(hsStream* stream, hsResMgr* mgr) HS_OVERRIDE;
};
class plVolumeSensorConditionalObjectNoArbitration : public plVolumeSensorConditionalObject
{
public:
plVolumeSensorConditionalObjectNoArbitration ():plVolumeSensorConditionalObject(){;}
~plVolumeSensorConditionalObjectNoArbitration (){;}
CLASSNAME_REGISTER( plVolumeSensorConditionalObjectNoArbitration );
GETINTERFACE_ANY( plVolumeSensorConditionalObjectNoArbitration, plConditionalObject );
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
protected:
plKey fHittee;
CLASSNAME_REGISTER(plVolumeSensorConditionalObjectNoArbitration);
GETINTERFACE_ANY( plVolumeSensorConditionalObjectNoArbitration, plVolumeSensorConditionalObject);
void Read(hsStream* stream, hsResMgr* mgr) HS_OVERRIDE;
};

View File

@ -3336,6 +3336,15 @@ PF_CONSOLE_CMD(Logic, WriteDetectorLog, "", "Write detector log to logfile")
DetectorDoLogfile();
}
PF_CONSOLE_CMD(Logic,
DelayArbitration,
"int millis",
"Simulates network delay for LogicMod arbitration")
{
int ms = params[0];
plLogicModBase::SetArbitrationDelay(ms);
}
#endif // LIMIT_CONSOLE_COMMANDS
////////////////////////////////////////////////////////////////////////

View File

@ -457,11 +457,3 @@ PF_CONSOLE_CMD( Game, SetLocalClientAsAdmin, "bool enable", "Makes chat messages
plgDispatch::MsgSend( msg );
}
#endif
#include "../pfConditional/plObjectInBoxConditionalObject.h"
PF_CONSOLE_CMD( Game, BreakVolumeSensors, "bool break", "reverts to old broken volume sensor logic" )
{
bool b = params[ 0 ];
plVolumeSensorConditionalObject::makeBriceHappyVar = !b;
}

View File

@ -993,3 +993,17 @@ void pySceneObject::VolumeSensorIgnoreExtraEnters(bool ignore)
}
}
}
void pySceneObject::VolumeSensorNoArbitration(bool noArbitration)
{
if (fSceneObjects.Count() > 0) {
plSceneObject* obj = plSceneObject::ConvertNoRef(fSceneObjects[0]->ObjectIsLoaded());
if (obj) {
for (size_t i = 0; i < obj->GetNumModifiers(); ++i) {
plLogicModifier* logic = const_cast<plLogicModifier*>(plLogicModifier::ConvertNoRef(obj->GetModifier(i)));
if (logic)
logic->VolumeNoArbitration(noArbitration);
}
}
}
}

View File

@ -200,6 +200,9 @@ public:
// hack for garrison
void VolumeSensorIgnoreExtraEnters(bool ignore);
/** More SubWorld hacks */
void VolumeSensorNoArbitration(bool noArbitration);
};
#endif // _pySceneObject_h_

View File

@ -452,6 +452,17 @@ PYTHON_METHOD_DEFINITION(ptSceneobject, volumeSensorIgnoreExtraEnters, args)
PYTHON_RETURN_NONE;
}
PYTHON_METHOD_DEFINITION(ptSceneobject, volumeSensorNoArbitration, args)
{
bool noArbitration = true;
if (!PyArg_ParseTuple(args, "|b", &noArbitration)) {
PyErr_SetString(PyExc_TypeError, "volumeSensorNoArbitration expects an optional boolean");
PYTHON_RETURN_ERROR;
}
self->fThis->VolumeSensorNoArbitration(noArbitration);
PYTHON_RETURN_NONE;
}
PYTHON_START_METHODS_TABLE(ptSceneobject)
PYTHON_METHOD(ptSceneobject, addKey, "Params: key\nMostly used internally.\n"
"Add another sceneobject ptKey"),
@ -510,6 +521,7 @@ PYTHON_START_METHODS_TABLE(ptSceneobject)
PYTHON_METHOD(ptSceneobject, getSoundIndex, "Params: sndComponentName\nGet the index of the requested sound component"),
PYTHON_METHOD(ptSceneobject, volumeSensorIgnoreExtraEnters, "Params: ignore\nTells the volume sensor attached to this object to ignore extra enters (default), or not (hack for garrison)."),
PYTHON_METHOD(ptSceneobject, volumeSensorNoArbitration, "Params: noArbitration\nTells the volume sensor attached to this object whether or not to negotiate exclusive locks with the server."),
PYTHON_END_METHODS_TABLE;
PYTHON_GET_DEFINITION(ptSceneobject, draw)