Jump to content

Steve_Yorkshire

Contributor
  • Posts

    353
  • Joined

  • Last visited

Everything posted by Steve_Yorkshire

  1. Just to note, movement animations will overrule and disable scripted animations, so if the AI/Player is moving they won't play the animation. You could mount an invisible weaponImage and have the animation play as a recoil animation.
  2. Select a player in the editor and go to shapeEditor->hints and it will display all the bones/nodes that that type of object expects or can have. Bip01, etc is mostly used for spine blending for recoil animations. http://i.imgur.com/ynpiciI.png
  3. I've had a bit more of play around using the subExplosion type found in explosion.cpp/h: //projectile.h class ProjectileData : public GameBaseData { //... public: enum ExplosionConsts { EC_MAX_EXPLOSIONS = 4, }; // variables set in datablock definition: //... S32 fadeDelay; // the IRangeValidatorScaled field validator /* ExplosionData* explosion; S32 explosionId; */ ExplosionData* explosionList[EC_MAX_EXPLOSIONS]; S32 explosionIDList[EC_MAX_EXPLOSIONS]; ExplosionData* waterExplosion; // Water Explosion Datablock //... //projectile.cpp //... void ProjectileData::initPersistFields() { //... //addField("explosion", TYPEID< ExplosionData >(), Offset(explosion, ProjectileData), // "@brief Explosion datablock used when the projectile explodes outside of water.\n\n"); addField("explosion", TYPEID< ExplosionData >(), Offset(explosionList, ProjectileData), EC_MAX_EXPLOSIONS, "List of additional ExplosionData objects to create at the start of the " "explosion."); addField("waterExplosion", TYPEID< ExplosionData >(), Offset(waterExplosion, ProjectileData), "@brief Explosion datablock used when the projectile explodes underwater.\n\n"); //... } //... bool ProjectileData::preload(bool server, String &errorStr) { //... Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet, bad datablockId(particleWaterEmitter): %d", particleWaterEmitterId); /* if (!explosion && explosionId != 0) if (Sim::findObject(explosionId, explosion) == false) Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet, bad datablockId(explosion): %d", explosionId); */ for (S32 k = 0; k { if (!explosionList[k] && explosionIDList[k] != 0) { if (Sim::findObject(explosionIDList[k], explosionList[k]) == false) { Con::errorf(ConsoleLogEntry::General, "ExplosionData::onAdd: Invalid packet, bad datablockId(explosion): 0x%x", explosionIDList[k]); } } } if (!waterExplosion && waterExplosionId != 0) //... } //... void ProjectileData::packData(BitStream* stream) { //... /* if (stream->writeFlag(explosion != NULL)) stream->writeRangedU32(explosion->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast); */ for (S32 i = 0; i { if (stream->writeFlag(explosionList != NULL)) { stream->writeRangedU32(explosionList->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast); } } if (stream->writeFlag(waterExplosion != NULL)) //... } void ProjectileData::unpackData(BitStream* stream) { //... /* if (stream->readFlag()) explosionId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast); */ for (S32 k = 0; k { if (stream->readFlag()) { explosionIDList[k] = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast); } } if (stream->readFlag()) waterExplosionId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast); //... } //... void Projectile::explode( const Point3F &p, const Point3F &n, const U32 collideType ) { //... } However it all rather ground to a halt because I am not familiar with how to get the explosionList[EC_MAX_EXPLOSIONS] in the actual explode() function of projectile.cpp. :?
  4. @TRON http://pbs.twimg.com/media/BvyOwM9IcAAtLcQ.jpg :P
  5. Projectiles are a little boring having only one explosion and if you want to use an animated particle sprite sheet or an explosion model it's going to get even more repetitive. Here's the general idea, the projectile has up to 4 explosion datablocks instead of 1. On exploding the projectile looks up how many explosion datablocks in can reference and then randomly chooses one. If it can't find any additional explosions it will default to the single stock one. Obviously you can do the same with water explosions, but ehre I'm only using dirt/dry explosions. I am currently in "art mode" so here's a - **warning of terrible C++ ahead** - feel free to expand on the idea and make it less horrible. First up, add new datablocks and information for explosions to the projectile. Here I am using the stock projectile in art/datablocks/Lurker.cs. This requires adding new particles and emitters, as well as editing the stock BulletDirtExplosion emitters to make it easier to see. //... datablock ParticleData(BulletDirtDust) { textureName = "art/particles/impact"; dragCoefficient = "1"; gravityCoefficient = "-0.100122"; windCoefficient = 0; inheritedVelFactor = 0.0; constantAcceleration = "-0.83"; lifetimeMS = 800; lifetimeVarianceMS = 300; spinRandomMin = -180.0; spinRandomMax = 180.0; useInvAlpha = true; colors[0] = "0.496063 0.393701 0.299213 0.692913"; colors[1] = "0.692913 0.614173 0.535433 0.346457"; colors[2] = "0.897638 0.84252 0.795276 0"; sizes[0] = "0.997986"; sizes[1] = "2"; sizes[2] = "2.5"; times[0] = 0.0; times[1] = "0.498039"; times[2] = 1.0; animTexName = "art/particles/impact"; }; datablock ParticleEmitterData(BulletDirtDustEmitter) { ejectionPeriodMS = 20; periodVarianceMS = 10; ejectionVelocity = "1"; velocityVariance = 1.0; thetaMin = 0.0; thetaMax = 180.0; lifetimeMS = 250; particles = "BulletDirtDust"; blendStyle = "ADDITIVE";//yorks "NORMAL"; }; //yorks start datablock ParticleData(BulletDirtDust1) { textureName = "art/particles/impact"; dragCoefficient = "1"; gravityCoefficient = "-0.1"; windCoefficient = 0; inheritedVelFactor = 0.0; constantAcceleration = "-0.83"; lifetimeMS = 800; lifetimeVarianceMS = 300; spinRandomMin = -180.0; spinRandomMax = 180.0; useInvAlpha = true; colors[0] = "1 0 0 0"; colors[1] = "1 0 0.0 0.5"; colors[2] = "1 0 0.0 0"; sizes[0] = "1"; sizes[1] = "2"; sizes[2] = "2.5"; times[0] = 0.0; times[1] = "0.5"; times[2] = 1.0; animTexName = "art/particles/impact"; }; datablock ParticleEmitterData(BulletDirtDust1Emitter) { ejectionPeriodMS = 20; periodVarianceMS = 10; ejectionVelocity = "1"; velocityVariance = 1.0; thetaMin = 0.0; thetaMax = 180.0; lifetimeMS = 250; particles = "BulletDirtDust1"; blendStyle = "ADDITIVE"; }; datablock ParticleData(BulletDirtDust2) { textureName = "art/particles/impact"; dragCoefficient = "1"; gravityCoefficient = "-0.1"; windCoefficient = 0; inheritedVelFactor = 0.0; constantAcceleration = "-0.83"; lifetimeMS = 800; lifetimeVarianceMS = 300; spinRandomMin = -180.0; spinRandomMax = 180.0; useInvAlpha = true; colors[0] = "0.0 0.0 1 1"; colors[1] = "0.0 0.0 1 0.5"; colors[2] = "0.0 0.0 1 0"; sizes[0] = "1"; sizes[1] = "2"; sizes[2] = "3"; times[0] = 0.0; times[1] = "0.5"; times[2] = 1.0; animTexName = "art/particles/impact"; }; datablock ParticleEmitterData(BulletDirtDust2Emitter) { ejectionPeriodMS = 20; periodVarianceMS = 10; ejectionVelocity = "1"; velocityVariance = 1.0; thetaMin = 0.0; thetaMax = 180.0; lifetimeMS = 250; particles = "BulletDirtDust2"; blendStyle = "ADDITIVE"; }; datablock ParticleData(BulletDirtDust3) { textureName = "art/particles/impact"; dragCoefficient = "1"; gravityCoefficient = "-0.1"; windCoefficient = 0; inheritedVelFactor = 0.0; constantAcceleration = "-0.83"; lifetimeMS = 800; lifetimeVarianceMS = 300; spinRandomMin = -180.0; spinRandomMax = 180.0; useInvAlpha = true; colors[0] = "0.0 1 0 1"; colors[1] = "0.0 1 0 0.5"; colors[2] = "0.0 1 0 0"; sizes[0] = "1"; sizes[1] = "2"; sizes[2] = "3"; times[0] = 0.0; times[1] = "0.5"; times[2] = 1.0; animTexName = "art/particles/impact"; }; datablock ParticleEmitterData(BulletDirtDust3Emitter) { ejectionPeriodMS = 20; periodVarianceMS = 10; ejectionVelocity = "1"; velocityVariance = 1.0; thetaMin = 0.0; thetaMax = 180.0; lifetimeMS = 250; particles = "BulletDirtDust3"; blendStyle = "ADDITIVE"; }; //yorks end //----------------------------------------------------------------------------- // Explosion //----------------------------------------------------------------------------- datablock ExplosionData(BulletDirtExplosion) { soundProfile = BulletImpactSound; lifeTimeMS = 65; // Volume particles particleEmitter = BulletDirtDustEmitter; particleDensity = 4; particleRadius = 0.3; //yorks start /* // Point emission emitter[0] = BulletDirtSprayEmitter; emitter[1] = BulletDirtSprayEmitter; emitter[2] = BulletDirtRocksEmitter; */ // Point emission emitter[0] = BulletDirtDustEmitter; emitter[1] = BulletDirtDustEmitter; emitter[2] = BulletDirtDustEmitter; //yorks end }; //yorks start datablock ExplosionData(BulletDirtExplosion1) { soundProfile = BulletImpactSound; lifeTimeMS = 65; // Volume particles particleEmitter = BulletDirtDust1Emitter; particleDensity = 4; particleRadius = 0.3; // Point emission emitter[0] = BulletDirtDust1Emitter; emitter[1] = BulletDirtDust1Emitter; emitter[2] = BulletDirtDust1Emitter; }; datablock ExplosionData(BulletDirtExplosion2) { soundProfile = BulletImpactSound; lifeTimeMS = 65; // Volume particles particleEmitter = BulletDirtDust2Emitter; particleDensity = 4; particleRadius = 0.3; // Point emission emitter[0] = BulletDirtDust2Emitter; emitter[1] = BulletDirtDust2Emitter; emitter[2] = BulletDirtDust2Emitter; }; datablock ExplosionData(BulletDirtExplosion3) { soundProfile = BulletImpactSound; lifeTimeMS = 65; // Volume particles particleEmitter = BulletDirtDust3Emitter; particleDensity = 4; particleRadius = 0.3; // Point emission emitter[0] = BulletDirtDust3Emitter; emitter[1] = BulletDirtDust3Emitter; emitter[2] = BulletDirtDust3Emitter; }; //yorks end //... datablock ProjectileData( BulletProjectile ) { projectileShapeName = ""; directDamage = 5; radiusDamage = 0; damageRadius = 0.5; areaImpulse = 0.5; impactForce = 1; explosion = BulletDirtExplosion; decal = BulletHoleDecal; //yorks start explosion1 = BulletDirtExplosion1; explosion2 = BulletDirtExplosion2; explosion3 = BulletDirtExplosion3; //yorks end muzzleVelocity = 120; velInheritFactor = 1; armingDelay = 0; lifetime = 992; fadeDelay = 1472; bounceElasticity = 0; bounceFriction = 0; isBallistic = false; gravityMod = 1; }; //... So we have now have 4 explosions which will show white (original), red, blue and green so we can see the difference. Next up we need to crack open the C++. Open up soure/T3D/projectile.h and list the new explosion data. /... ExplosionData* explosion; S32 explosionId; //yorks start ExplosionData* explosion1; S32 explosion1Id; ExplosionData* explosion2; S32 explosion2Id; ExplosionData* explosion3; S32 explosion3Id; //yorks end ExplosionData* waterExplosion; // Water Explosion Datablock //... And then the meat of the sandwich, source/T3D/projectile.cpp. ProjectileData::ProjectileData() { //... explosion = NULL; explosionId = 0; //yorks start explosion1 = NULL; explosion1Id = 0; explosion2 = NULL; explosion2Id = 0; explosion3 = NULL; explosion3Id = 0; //yorks end waterExplosion = NULL; //... } //... void ProjectileData::initPersistFields() { //... addField("explosion", TYPEID< ExplosionData >(), Offset(explosion, ProjectileData), "@brief Explosion datablock used when the projectile explodes outside of water.\n\n"); addField("waterExplosion", TYPEID< ExplosionData >(), Offset(waterExplosion, ProjectileData), "@brief Explosion datablock used when the projectile explodes underwater.\n\n"); //yorks start addField("explosion1", TYPEID< ExplosionData >(), Offset(explosion1, ProjectileData), "@brief Explosion1 datablock used when the projectile explodes outside of water.\n\n"); addField("explosion2", TYPEID< ExplosionData >(), Offset(explosion2, ProjectileData), "@brief Explosion2 datablock used when the projectile explodes outside of water.\n\n"); addField("explosion3", TYPEID< ExplosionData >(), Offset(explosion3, ProjectileData), "@brief Explosion3 datablock used when the projectile explodes outside of water.\n\n"); //yorks end addField("splash", TYPEID< SplashData >(), Offset(splash, ProjectileData), "@brief Splash datablock used to create splash effects as the projectile enters or leaves water\n\n"); //... } //... bool ProjectileData::preload(bool server, String &errorStr) { //... if (!explosion && explosionId != 0) if (Sim::findObject(explosionId, explosion) == false) Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet, bad datablockId(explosion): %d", explosionId); //yorks start if (!explosion1 && explosion1Id != 0) if (Sim::findObject(explosion1Id, explosion1) == false) Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet, bad datablockId(explosion1): %d", explosion1Id); if (!explosion2 && explosion2Id != 0) if (Sim::findObject(explosion2Id, explosion2) == false) Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet, bad datablockId(explosion2): %d", explosion2Id); if (!explosion3 && explosion3Id != 0) if (Sim::findObject(explosion3Id, explosion3) == false) Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet, bad datablockId(explosion3): %d", explosion3Id); //yorks end if (!waterExplosion && waterExplosionId != 0) //... } //-------------------------------------------------------------------------- void ProjectileData::packData(BitStream* stream) { //... if (stream->writeFlag(explosion != NULL)) stream->writeRangedU32(explosion->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast); //yorks start if (stream->writeFlag(explosion1 != NULL)) stream->writeRangedU32(explosion1->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast); if (stream->writeFlag(explosion2 != NULL)) stream->writeRangedU32(explosion2->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast); if (stream->writeFlag(explosion3 != NULL)) stream->writeRangedU32(explosion3->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast); //yorks end if (stream->writeFlag(waterExplosion != NULL)) //... } void ProjectileData::unpackData(BitStream* stream) { //... if (stream->readFlag()) explosionId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast); //yorks start if (stream->readFlag()) explosion1Id = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast); if (stream->readFlag()) explosion2Id = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast); if (stream->readFlag()) explosion3Id = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast); //yorks end if (stream->readFlag()) //... } //... void Projectile::explode( const Point3F &p, const Point3F &n, const U32 collideType ) { //... else { // Client just plays the explosion at the right place... // Explosion* pExplosion = NULL; //yorks in S32 mRandomize = 0; if (mDataBlock->waterExplosion && pointInWater(p)) { pExplosion = new Explosion; pExplosion->onNewDataBlock(mDataBlock->waterExplosion, false); } else /*yorks out start if (mDataBlock->explosion) { pExplosion = new Explosion; pExplosion->onNewDataBlock(mDataBlock->explosion, false); } //yorks out end */ //yorks in start { //yorks start with 1 continue check with others if exists else default to normal explosion if (mDataBlock->explosion1) { //yorks we have >1 explosion, check for others if (mDataBlock->explosion2) { if (mDataBlock->explosion3) mRandomize = 3; else mRandomize = 2; } else mRandomize = 1; } //yorks get the random if (mRandomize == 0) { //stock explosion if (mDataBlock->explosion) { pExplosion = new Explosion; pExplosion->onNewDataBlock(mDataBlock->explosion, false); } } else { //yorks get random number betweem 0 and mRandomize S32 mChoose = (gRandGen.randI(0, mRandomize)); if (mChoose == 1) { pExplosion = new Explosion; pExplosion->onNewDataBlock(mDataBlock->explosion1, false); } else { if (mChoose == 2) { pExplosion = new Explosion; pExplosion->onNewDataBlock(mDataBlock->explosion2, false); } else { if (mChoose == 3) { pExplosion = new Explosion; pExplosion->onNewDataBlock(mDataBlock->explosion3, false); } else { pExplosion = new Explosion; pExplosion->onNewDataBlock(mDataBlock->explosion, false); } } } } } //yorks in end if( pExplosion ) //... } //... And that should be that. It ain't elegant but it works, as I said up top, feel free to improve it (no really plz). :lol: And this is what it looks like in action: KdaqnWd11Ck
  6. Nvidia releasing bad drivers? Not like that ever happened before. #burn
  7. Nice! I like the HUD icons a lot. :D Also, resource your minmap code!
  8. Whilst playing around with 3.8 I've found a rather horrifying bug: When using the Material Editor or the Particle Emitter Editor, they have a nasty tendency to overwrite other datablock definitions. :evil: example: singleton Material(base1) { mapTo = "base1"; //etc } singleton Material(base2) { mapTo = "base2"; //etc } becomes: singleton Material(base2) { mapTo = "base2"; //etc } singleton Material(base2) { mapTo = "base2"; //etc } And you won't notice until you restart T3D and material Base1 is missing and shows up with the orange no material image. This also happens with data saved through particleEmitters, though not particle datablocks. As I've been making lots of changes with Material and ParticleEmitter editors I have noticed this wrong overwriting to be happening a lot. However I've not noticed doing a particular "thing" to cause it. Sometimes it's fine - but eventually it won't be. This was not a problem I noticed making AirDrag, but mostly spent the last few releases of Torque updating existing stuff rather than creating new stuff with the editors, so I cannot say when this started happening. Note: tested messing around with materials on both custom and stock 3.8 builds and both suffer from this issue so it's not something my custom code introduced. Has anyone been intensitvely using matieral or particle editors and noticed this issue? :|
  9. Here's an old outline shader, incase it helps. http://yorkshirerifles.com/random/outline_shader.zip ;)
  10. I wrote up a blog post on my attempts to create animated textures for a static grass mesh. http://forums.torque3d.org/viewtopic.php?f=8&t=561
  11. @Nils actually it's all tsStatic mesh. For my new project I'm not using the stock terrain system at all.
  12. Editing Normals Modifier has been a thing since Blender 2.7 apparently. And here it is in action! :D http://yorkshirerifles.com/random/editedNormals.jpg
  13. Love the Gorn! :) Note to self: never wear a red shirt ;)
  14. Added a fix to the thread body below the original posting.
  15. FIXED: SEE BELOW Whilst 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 2016 Fixed 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.h We 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.zip As always, feedback and improvements welcome. proxMine_yorks.zip C++
  16. @rlranft Don't think I have copies of them anymore, and I'm not about to go looking through gigs of badly named backups ;)
  17. Some of the old free upload/hosts seem to have bugged/deleted some of my old pics - which is annoying but hey, get what you pay for. :/ Just to note, all my old tutorials should be good with teh exception that $typemasks::TsStatic (or whatever it was called) no longer exists and needs updating to $TypeMasks::StaticObjectType - but apart from that, should work as written. So ... How To Into MMO not getting much traction, then? ;) :P :mrgreen:
  18. http://i.imgur.com/s9LfSbO.jpg Humbug
  19. http://i.imgur.com/t0JkkF7.jpg [mention]Bloodknight[/mention] confirmed for iterally worse thanStarfish Hitler :evil: :mrgreen:
  20. Not found any issues playing around with Az's afx3.8 branch ... which is nice. :)
  21. Adding engineAPI.h to arcaneFX.h threw up 122 "unresolved external symbols" relating to "onStaticModified". Adding engineAPI.h individually to the 5 error files stopped the original errors, until all 5 files had it, then it threw the above 122 errors again. Adding console/console.h had no effect on original errors. I mostly code gameplay and new classes so this bit of the engine is rather baffling. Also I notice Jeff had missed a few code comments so shockWaveData wasn't covered in his port, but it was easy to fix those errors.
×
×
  • Create New...