/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #include "hsTypes.h" #include "plObjectInBoxConditionalObject.h" #include "../../PubUtilLib/plPhysical/plDetectorModifier.h" #include "../../NucleusLib/pnModifier/plLogicModBase.h" #include "../../PubUtilLib/plMessage/plActivatorMsg.h" #include "../pnMessage/plNotifyMsg.h" #include "../pnMessage/plFakeOutMsg.h" #include "../pnNetCommon/plNetApp.h" #include "../plAvatar/plArmatureMod.h" #include "../pnSceneObject/plSceneObject.h" bool plVolumeSensorConditionalObject::makeBriceHappyVar = true; plObjectInBoxConditionalObject::plObjectInBoxConditionalObject() : fCurrentTrigger(nil) { SetSatisfied(true); } hsBool plObjectInBoxConditionalObject::MsgReceive(plMessage* msg) { plActivatorMsg* pActivateMsg = plActivatorMsg::ConvertNoRef(msg); if (pActivateMsg) { if (pActivateMsg->fTriggerType == plActivatorMsg::kVolumeEnter) { fInside.Append(pActivateMsg->fHitterObj); return true; } else if (pActivateMsg->fTriggerType == plActivatorMsg::kVolumeExit) { for (int i = 0; i < fInside.Count(); i++) { if (fInside[i] == pActivateMsg->fHitterObj) { fInside.Remove(i); if (pActivateMsg->fHitterObj == fCurrentTrigger && fCurrentTrigger && fLogicMod->HasFlag(plLogicModBase::kTriggered) && !IsToggle()) { fCurrentTrigger = nil; fLogicMod->GetNotify()->AddContainerEvent( pActivateMsg->fHiteeObj, pActivateMsg->fHitterObj, false ); fLogicMod->RequestUnTrigger(); } } } return true; } return false; } return plConditionalObject::MsgReceive(msg); } hsBool plObjectInBoxConditionalObject::Verify(plMessage* msg) { plActivatorMsg* pActivateMsg = plActivatorMsg::ConvertNoRef(msg); if (pActivateMsg) { for (int i = 0; i < fInside.Count(); i++) { if (pActivateMsg->fHitterObj == fInside[i]) { fLogicMod->GetNotify()->AddContainerEvent( pActivateMsg->fHiteeObj, pActivateMsg->fHitterObj, true ); fCurrentTrigger = pActivateMsg->fHiteeObj; return true; } } } plFakeOutMsg* pFakeMsg = plFakeOutMsg::ConvertNoRef(msg); if (pFakeMsg && plNetClientApp::GetInstance()->GetLocalPlayerKey()) { for (int i = 0; i < fInside.Count(); i++) { if (plNetClientApp::GetInstance()->GetLocalPlayerKey() == fInside[i]) return true; } } return false; } // // volume sensor conditional // plVolumeSensorConditionalObject::plVolumeSensorConditionalObject() : fTrigNum(-1), fType(0), fFirst(false), fTriggered(false), fIgnoreExtraEnters(true) { SetSatisfied(true); } hsBool plVolumeSensorConditionalObject::MsgReceive(plMessage* msg) { plActivatorMsg* pActivateMsg = plActivatorMsg::ConvertNoRef(msg); if (pActivateMsg) { // single player hack if (!fLogicMod->HasFlag(plLogicModBase::kRequestingTrigger)) fLogicMod->GetNotify()->ClearEvents(); 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::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); } else { fLogicMod->GetNotify()->AddCollisionEvent(false, pActivateMsg->fHitterObj, pActivateMsg->fHiteeObj, false); fLogicMod->RequestUnTrigger(); } 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::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; } } } return false; } return plConditionalObject::MsgReceive(msg); } hsBool plVolumeSensorConditionalObject::Satisfied() { if (fType == kTypeExit && fFirst && !fTriggered) { if (fInside.Count()) fTriggered = true; return true; } if (fTriggered) { if (fInside.Count() == 0) fTriggered = false; return false; } if (fTrigNum == -1) return true; if (fInside.Count() == fTrigNum) return true; else return false; } void plVolumeSensorConditionalObject::Read(hsStream* stream, hsResMgr* mgr) { plConditionalObject::Read(stream, mgr); fTrigNum = stream->ReadSwap32(); fType = stream->ReadSwap32(); fFirst = stream->ReadBool(); } void plVolumeSensorConditionalObject::Write(hsStream* stream, hsResMgr* mgr) { plConditionalObject::Write(stream, mgr); stream->WriteSwap32(fTrigNum); 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::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::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()); }