Steve_Yorkshire Posted January 11, 2016 Share Posted January 11, 2016 (edited) FIXED: SEE BELOWWhilst looking through the stock code, I noticed that ProximityMine.cpp/h checks for mOwner and triggerOnOwner(bool) to set whether you want it to explode on the original owner of the mine or not ---- except mOwner can never be set. // Detect movement in the trigger area if ( ( sql.mList == mOwner && !mDataBlock->triggerOnOwner ) || sql.mList->getVelocity().len() < mDataBlock->triggerSpeed ) continue;mOwner and triggerOnOwner called when it decides if it should explode (line ~444) but as mOwner is always null it always explodes. Note: when in scripts/server/proximityMine.cs onThrow functionthe object has a "sourceObject" defined like projectiles, but unlike projectiles there is nothing to refer to this in C++.So, thoughts on best fix?1: Add a setOwner engineDefine and do it manually from script (feels a bit of a faff)2: Add the script definition of sourceObject into C++ to be the mOwner variable, like projectile.cpp does and pack/unpack it.eg: inside initPersistFields and change mSourceObjectId to mOwner:addGroup("Source"); addField("sourceObject", TypeS32, Offset(mSourceObjectId, Projectile), "@brief ID number of the object that fired the projectile.\n\n" "@note If the projectile was fired by a WeaponImage, sourceObject will be " "the object that owns the WeaponImage. This is usually the player.");I expect #2 is the better option but thought I'd ask for opinions.//edit 24 Jan 2016Fixed this. Also killed 2 birds with 1 stone by making "sourceObject" in the ProximityMineData::onThrow function in scripts/server/proximityMine.cs used for setting and checking the mine's owner. If someone else triggers the mine, the owner can still be damaged if they are close to the blast.The only downside which I have found is that the player collides with the mine as it has no "step" function for it's collision. Owner has to jump on/over the mine to move through it.Stock code from scripts/server/proximityMine.cs, sourceObject now referenced in C++function ProximityMineData::onThrow( %this, %user, %amount ) { // Remove the object from the inventory %user.decInventory( %this, 1 ); // Construct the actual object in the world, and add it to // the mission group so its cleaned up when the mission is // done. The object is given a random z rotation. %obj = new ProximityMine() { datablock = %this; sourceObject = %user; rotation = "0 0 1 "@ (getRandom() * 360); static = false; client = %user.client; }; MissionCleanup.add(%obj); return %obj; }===============================================================================TorqueScript Changes: art/datablocks/weapons/proxMine.cs //... datablock ProximityMineData( ProxMine ) { //... autoTriggerDelay = 0; triggerOnOwner = false;//stock = true; WHETHER THE OWNER TRIGGERS THE MINE triggerRadius = 3.0; //...-----------------------------------------------C++ Changes: source/T3D/proximityMine.hWe get rid of "mOwner" and replace it with sourceObjectId and a pointer to the ghost, just like in projectile.cpp. class ProximityMine: public Item { typedef Item Parent; protected: //... TSThread* mAnimThread; //SceneObject* mOwner;//<----- yorks out, use sourceObjectId now State mState; //... void renderObject( ObjectRenderInst* ri, SceneRenderState* state, BaseMatInstance* overrideMat ); //<-------- yorks in start S32 mSourceObjectId; SimObjectPtr mSourceObject; ///< Actual pointer to the source object, times out after SourceIdTimeoutTicks //<-------- yorks in end public: DECLARE_CONOBJECT( ProximityMine ); //... bool onAdd(); void onRemove(); bool onNewDataBlock( GameBaseData* dptr, bool reload ); static void initPersistFields();//<---------- yorks new in to get sourceObject set from script virtual void setTransform( const MatrixF& mat ); //... void unpackUpdate( NetConnection* conn, BitStream* stream ); S32 getOwnerID() { return mSourceObjectId; }//<------- yorks new in }; #endif // _PROXIMITYMINE_H_source/T3D/proximityMine.cpp //... ProximityMine::ProximityMine() { mTypeMask |= StaticShapeObjectType; //... // For the Item class mSubclassItemHandlesScene = true; mSourceObjectId = -1;//<---------- yorks in } ProximityMine::~ProximityMine() { } //<------ yorks in start void ProximityMine::initPersistFields() { addGroup("Source"); addField("sourceObject", TypeS32, Offset(mSourceObjectId, ProximityMine), "@brief ID number of the object that fired the mine.\n\n" "@note This is usually the player."); endGroup("Source"); Parent::initPersistFields(); } //<------- yorks in end //... bool ProximityMine::onAdd() { if ( !Parent::onAdd() || !mDataBlock ) return false; addToScene(); //<----- yorks out start //if (isServerObject()) //scriptOnAdd(); //<----- yorks out end //<-------- yorks in start if (isServerObject()) { ShapeBase* ptr; if (Sim::findObject(mSourceObjectId, ptr)) { mSourceObject = ptr; // Since we later do processAfter( mSourceObject ) we must clearProcessAfter // if it is deleted. SceneObject already handles this in onDeleteNotify so // all we need to do is register for the notification. deleteNotify(ptr); } else { if (mSourceObjectId != -1) Con::errorf(ConsoleLogEntry::General, "ProximityMine::onAdd: mSourceObjectId is invalid"); mSourceObject = NULL; } } else { if (mSourceObject.isValid()) processAfter(mSourceObject); } //<------ yorks in end if ( mStatic ) { // static mines are armed immediately mState = Deployed; mStateTimeout = 0; } return true; } //... void ProximityMine::processTick( const Move* move ) { //... SimpleQueryList::insertionCallback, &sql ); for ( S32 i = 0; i < sql.mList.size(); i++ ) { //<---- yorks out start - not using mOwner now /* // Detect movement in the trigger area if ( ( sql.mList == mOwner && !mDataBlock->triggerOnOwner ) || sql.mList->getVelocity().len() < mDataBlock->triggerSpeed ) continue; */ //<---- yorks out end - not using mOwner now //<---- yorks in start - now using mSourceObject, and check it's valid if ((mSourceObject.isValid() && sql.mList == mSourceObject && !mDataBlock->triggerOnOwner) || sql.mList->getVelocity().len() < mDataBlock->triggerSpeed) continue; //<---- yorks in end - now using mSourceObject, and check it's valid // Mine has been triggered mShapeInstance->destroyThread( mAnimThread ); mAnimThread = NULL; //... U32 ProximityMine::packUpdate( NetConnection* connection, U32 mask, BitStream* stream ) { //... stream->writeFlag( ( mask & ExplosionMask ) && ( mState == Exploded ) ); //yorks in start if (mSourceObject.isValid()) { // Potentially have to write this to the client, let's make sure it has a // ghost on the other side... //yorks this is from projectile so not sure if this is true for proximityMine S32 ghostIndex = connection->getGhostIndex(mSourceObject); if (stream->writeFlag(ghostIndex != -1)) { stream->writeRangedU32(U32(ghostIndex), 0, NetConnection::MaxGhostCount); } else // have not recieved the ghost for the source object yet, try again later retMask |= GameBase::InitialUpdateMask; } else stream->writeFlag(false); //yorks in end return retMask; } void ProximityMine::unpackUpdate( NetConnection* connection, BitStream* stream ) { //... if ( mStatic && mState <= Deployed ) { // static mines are armed immediately mState = Deployed; mStateTimeout = 0; } //<------------ yorks in start if (stream->readFlag()) { mSourceObjectId = stream->readRangedU32(0, NetConnection::MaxGhostCount); NetObject* pObject = connection->resolveGhost(mSourceObjectId); if (pObject != NULL) mSourceObject = dynamic_cast(pObject); } else { mSourceObjectId = -1; mSourceObject = NULL; } //<------- yorks in end } //... //right at the bottom add a TS function for debug testing the mine's sourceObject DefineEngineMethod(ProximityMine, getOwner, S32, (), , "@brief Get the owner of the proximity mine.\n\n" "@returns mSourceObjectId.") { return object->getOwnerID(); }And here's the source for download:http://yorkshirerifles.com/downloads/proxMine_yorks.zipAs always, feedback and improvements welcome.proxMine_yorks.zipC++ Edited January 24, 2016 by Steve_Yorkshire Quote Link to comment Share on other sites More sharing options...
Nils Posted January 18, 2016 Share Posted January 18, 2016 Good one @Steve_Yorkshire, sometimes wondered why it didn't work.I would go for option 2 :) Quote Link to comment Share on other sites More sharing options...
Steve_Yorkshire Posted January 24, 2016 Author Share Posted January 24, 2016 Added a fix to the thread body below the original posting. Quote Link to comment Share on other sites More sharing options...
Nils Posted January 25, 2016 Share Posted January 25, 2016 Awesome! Thanks for sharing :) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.