Jason Campbell Posted February 23, 2017 Share Posted February 23, 2017 I recently have been using Torque 3D 3.5 in WINE on Linux so I can utilize Bryce's incredible Tactical AI Kit. Nothing would make me happier then getting TAIK to work natively in Linux. Looking at the changes, it may be possible even in 3,10. I could continue in 3.5 but there are some issues with using WINE, crashes and what not, though performance is surprisingly good. My questions is basically, how do I add new files to the Engine if I can't use the Project Solution from Visual Studio? How do I add files,filters and existing items using CMAKE?Any help or tips would be greatly appreciated. Quote Link to comment Share on other sites More sharing options...
Azaezel Posted February 25, 2017 Share Posted February 25, 2017 https://github.com/Azaezel/Torque3D/blob/afx_plus_devhead/Tools/CMake/modules/module_afx.cmake that'd be one way. Quote Link to comment Share on other sites More sharing options...
Jason Campbell Posted February 25, 2017 Author Share Posted February 25, 2017 Thanks, that might work. Plus, I was wondering exactly how to add modules anyway. The reason it might not work is that, there is a folder named recast inside of a folder named nav and his example in Visual studio has recast nested in nav, as "filters". I thought I had it set up in Code::Blocks but I can't do it again.Anyway, just to clarify, I could add afx using CMAKE GUI or by editing CMakeCache.txt?Thanks for responding. Quote Link to comment Share on other sites More sharing options...
Azaezel Posted February 25, 2017 Share Posted February 25, 2017 That method above adds a (pre-flipped) flag to cmake gui. Recast is already included in head, so won't need to do so twice. Quote Link to comment Share on other sites More sharing options...
Jason Campbell Posted February 25, 2017 Author Share Posted February 25, 2017 OK now I get it. I also think I'm beginning to understand why they are called filters. The Tactical AI Kit must use a modified recast. I'll look more Intel VS and what is meant by filters. Quote Link to comment Share on other sites More sharing options...
Jason Campbell Posted February 28, 2017 Author Share Posted February 28, 2017 God, I'm so close to getting this working. Originally Bryce said that any NavMesh and Recast will work fine as long as NavMesh is called Mesh1.Well I finally got it to Build with 0 errors and everything seems to work except the NavMesh is not seen. The AI tries to walk the NavPath but fails. Here is the error ==>SpawnAI(0,0,2); No NavMesh polygon near visit point (0, 0, 0) of NavPath 21855 brain.weapon = TAIKGunImage, brain.ammo = TAIKGunAmmo AI player spawned. Id: 21852. Team: 0. Brain: 21856 21852 No NavMesh polygon near visit point (32.0894, 44.4581, 4.63566) of NavPath 21855 Set::getObject - index out of range. scripts/server/ai/aiplayer/aiplayer.cs (862): Unable to find object: '' attempting to call function 'getPosition' 21852: On path 20701, moving to node at index 0 No NavMesh polygon near visit point (32.0894, 44.4581, 4.63566) of NavPath 21855 Set::getObject - index out of range. scripts/server/ai/aiplayer/aiplayer.cs (862): Unable to find object: '' attempting to call function 'getPosition' 21852: On path 20701, moving to node at index 0 I saw this error in an old GG post of Daniel's and tried his suggestion of changing mTypeMask |= StaticShapeObjectType | MarkerObjectType; to mTypeMask |= MarkerObjectType; but that didn't fix it.This is killing me. Any suggestion, please.One other thing. I'm getting a crash every so often Torque3D-3.10/Engine/source/core/stream/bitStream.cpp(339,0): {Fatal} - BitStream::writeInt: value out of range: -23/128 (7 bits) I searched and it seems to be a network problem? I'm not checking my network when it occurs. Any thoughts on that would be appreciated.Thank you Quote Link to comment Share on other sites More sharing options...
Azaezel Posted February 28, 2017 Share Posted February 28, 2017 Well, I can say -23/128 (7 bits) report tells us you're sending something along the network that expects a 7 bit range of 0-128, and it thinks youre trying to feed it a -23 (could be that, or could be wrapping. Half the reason for throwing that in for folks a while back was it used to be a silent network leak that would corrupt other stuff down the line. With that, should be able to turn up the exact cause with a stack trace.) Quote Link to comment Share on other sites More sharing options...
Jason Campbell Posted February 28, 2017 Author Share Posted February 28, 2017 Don't mean to be a pain but could you point in the direction of how to go about doing a stack trace?I used to be able to debug with Torsion but doesn't work with linux.Thanks Quote Link to comment Share on other sites More sharing options...
Azaezel Posted February 28, 2017 Share Posted February 28, 2017 http://darkdust.net/files/GDB%20Cheat%20Sheet.pdf cheat sheethttps://github.com/GarageGames/Torque3D/blob/c83efa59e0a11fc15c68afaf106807643191ac6f/Engine/source/T3D/gameBase/gameConnection.cpp#L1399 and you'll be looking for a line along those lines ( note the 7 bit length specification matching the error report.) Quote Link to comment Share on other sites More sharing options...
Jason Campbell Posted March 12, 2017 Author Share Posted March 12, 2017 I can't believe but it appears I have everything working correctly. I didn't think I would get this far really. I seemed to have squashed the other "value out range" problems but have a new one and I'm going mad. I haven't slept well in days. Okay.This is the new one Engine/source/core/stream/bitStream.cpp(339,0): {Fatal} - BitStream::writeInt: value out of range: -1/64 (6 bits) I'm pretty sure it stems from this in player.cppstream->writeSignedFloat(fTranquilized, 6); It seems to be a variable that effects speed while the players are zoomed and it crashes almost every time when I'm getting melee'd by an AIPlayer.I'm just going to post the snippets from everywhere I can find it. Maybe if someone can think of a work around to keep it a positive number or something. It seems to be consistently fatal with a -1 value.Any help would be appreciated. Thank you.player.h488 F32 fTranquilized; 733 void Player::setTranquilized(const F32 & tranquilized); 734 const F32 & Player::getTranquilized(); player.cpp1673 fTranquilized=0.0f; 2801 if(doStandardMove) 2802 { 2803 F32 p = move->pitch * (mPose == SprintPose ? mDataBlock->sprintPitchScale : 1.0f); 2804 if (fTranquilized>0.0f) p+=fTranquilized * mSin((F32)Sim::getCurrentTime()/200.0f); //TAIKWeapons++ 2805 if (p > M_PI_F) 2806 p -= M_2PI_F; 2807 mHead.x = mClampF(mHead.x + p,mDataBlock->minLookAngle, 2808 mDataBlock->maxLookAngle); 2836 F32 y = move->yaw * (mPose == SprintPose ? mDataBlock->sprintYawScale : 1.0f); 2837 if (fTranquilized>0.0f) y+=fTranquilized * mCos((F32)Sim::getCurrentTime()/300.0f); //TAIKWeapons++ 2838 if (y > M_PI_F) 2839 y -= M_2PI_F; 6833 stream->writeSignedFloat(fTranquilized, 6); 6929 fTranquilized = stream->readSignedFloat(6); (lines 7131 to 7149) ConsoleMethod( Player, IsTranquilized, F32, 2, 2, "Return if tranquilizer is enabled.") { Player* obj = static_cast(object); return obj->getTranquilized(); } ConsoleMethod( Player, SetTranquilized, void, 3, 3, "(F32) Sets tranquilizer.") { Player* obj = static_cast(object); obj->setTranquilized(dAtof(argv[2])); } const F32 & Player::getTranquilized() { return fTranquilized; } void Player::setTranquilized(const F32 & tranquilized) { fTranquilized = tranquilized; } TorqueScript(TAIKZoom.cs)function serverCmdCallZoomFunction( %client, %out ) { %zoomer = %client.getControlObject(); //%curWeapon = %zoomer.getMountedImage($WeaponSlot).item.getName(); //%curWeapon = %zoomer.getMountedImage($WeaponSlot); %zoomer.handleZoom(%out); } function Player::handleZoom(%this,%out) { %iS = %this.getImageState(0); if (%this.isLeaning && !%out) return; if (%is $= "GLReady" || %is $= "GLActivate" || %is $= "GLPutAway" || %is $= "GLReload") return; if (%iS $= "ReloadClip") %out = true; if (%iS !$= "Ready" && %is !$= "NoAmmo" && %is !$= "DryFire" && %is !$= "Activate") %out = true; if (!%this.zoomOn && !%out) { %this.zoomOn = true; %this.setSpeedMult(0.5); %this.setTranquilized(0.0002); // Figure out what type of sights we should be using if (%this.getMountedImage(2)) { if (%this.getMountedImage(2).getName() $= "M68Image" || %this.getMountedImage(2).getName() $= "SquareDotImage" || %this.getMountedImage(2).getName() $= "CMoreImage" || %this.getMountedImage(2).getName() $= "GlockDotImage" || %this.getMountedImage(2).getName() $= "EOTechImage" || %this.getMountedImage(2).getName() $= "AKDotImage" || %this.getMountedImage(2).getName() $= "F2000DotImage") { // Red dot %sightType = 2; } else if (%this.getMountedImage(2).getName() $= "AUGScopeImage") { //2x AUG Scope %sightType = 5; } else if (%this.getMountedImage(2).getName() $= "M4HandleImage" || %this.getMountedImage(2).getName() $= "M16HandleImage" || %this.getMountedImage(2).getName() $= "F2000IronImage") { // Iron sight %sightType = 1; } else { // ACOG if (%this.getMountedImage(2).getName() $= "ACOG1Image" || %this.getMountedImage(2).getName() $= "AKACOGImage") %sightType = 3; else %sightType = 4; // Default sniper scope } } else { if (%this.getMountedImage(0).permanentScope) { // Scope that cannot be dismounted %sightType = 3; } else { // Iron sights %sightType = 1; } } } else { %this.zoomOn = false; %sightType = 0; %this.setSpeedMult(1.0); %this.setTranquilized(0); } %cScope = %this.getMountedImage(0).scope; %wName = %this.getMountedImage(0).getName(); if (%wName $= "M24Image" || %wName $= "M110Image" || %wName $= "M14Image") if (%sightType != 3) %cScope = "M24Scope"; commandToClient(%this.client,'ZoomClientSide',%sightType,%this.getMountedImage(0).getName(),%cScope); } Quote Link to comment Share on other sites More sharing options...
Jason Campbell Posted March 13, 2017 Author Share Posted March 13, 2017 I'm wrong about where that error is stemming from. Is there a way to remove the Fatal crash interupt if I was just doing singleplayer?edit: there isn't a memory leak or anything, just that -1 Bitstream Quote Link to comment Share on other sites More sharing options...
JeffR Posted March 13, 2017 Share Posted March 13, 2017 So the only time it's happening at this point is when you get melee'd while zooming? Not just simply getting melee'd? Quote Link to comment Share on other sites More sharing options...
Jason Campbell Posted March 13, 2017 Author Share Posted March 13, 2017 It appears to happen when an AI melee's another AI from the front. It's attack3 and it may stem from an animation call that returns a negarive. Quote Link to comment Share on other sites More sharing options...
JeffR Posted March 14, 2017 Share Posted March 14, 2017 Hm, I think I'd run into something similar a few weeks back, where it had an issue with playing a bad animation, or a stopped animation or something. I'll poke around on my side and see if I can replicate it again. Quote Link to comment Share on other sites More sharing options...
Jason Campbell Posted March 14, 2017 Author Share Posted March 14, 2017 Dude, you probably have enough on your plate. Heh.I decided to try and eliminate all other errors in the console first and don't why I didn't notice this. Since it seemed to always occur during "fight3" I bypassed it for a bit and it became the next AI Melee TakeDown, in this case attack2. All sounds seem to work but this is clearly a problem. SFXProfile((null))::onAdd: The preload failed! SFXSound::_create() - Could not create device buffer! SFXSystem::createSource() - Failed to create sound! Profile: (null) Filename: Loading SFX: art/sound/TAIKTakedowns/fight2 (1 channels, 44 kHz, 3.83 sec, 330 kb) Could it be that simple as a Null in SFX? If so I don't get where to hunt this down. This is the Takedown audio code but from the echos and also that it loads the right sound, it seems to work. function playFightAudio(%person,%description,%filename,%pos) { %person.fightSoundSource = sfxPlayOnce(%description,"art/sound/TAIKTakedowns/" @ %filename,getWord(%pos,0),getWord(%pos,1),getWord(%pos,2)); echo("person" @ %person.fightSoundSource); echo(%filename); echo(%pos); // Make AIPlayers turn their heads if this happens close to them // The idea is that if we're going to stab someone standing next to their friend... // ...their friend should probably notice the scuffle. AlertAIPlayers(%person.getPosition(),8,0,"Annoyance",1,%person,0,0,%person.team); } edit: Found this and it looks complicated enough... function attack3(%win,%lose) { %prefix = "FT3_"; // Animation name is this + "loser" or "winner", e.g. FT1_Winner, or FT1_Loser %winOffsetFromLose = "0 1 0"; // Winner should perform this takedown 1m in front of loser %loseOffsetFromWin = ""; // Loser of this takedown should stay put %initPadTime = 100; // 10ms before playing animations, enough time to get everyone to stop what they're doing %lookCode = 1; // 1 = Winner looks toward loser, 2= loser looks toward winner %winFightTime = 2200 + %initPadTime; // Time in ms until the winner is done with the fight, and control is re-acquired. %loseFightTime = 3500 + %initPadTime; // How long until the loser is given their control binds back (though they're dead, they may want to respawn) %noReturnTime = 1340; // Time (ms) until victim is officially dead. %lose can escape the fight if %win dies before this time has elapsed. %disarmTime = 3300; // Time (ms) until victim drops their gun %p = %win.prepActor(%lose,%winOffsetFromLose,%loseOffsetFromWin,%lookCode); if (%p == -1) return; %lose.prepActor(%win,"","",0); %lose.fightKiller = %win; %win.fightVictim = %lose; %win.ensureLookingAtVictim(%lose,%winFightTime); schedule(%initPadTime,0,attack3_action,%win,%lose,%prefix); %lose.schedule(%noReturnTime,takedownDeath,%win); %win.weaponSched[0] = %win.schedule(500,mountImage,TAIKKnifeImage,0); %win.schedule(%winFightTime,leaveFight); %lose.schedule(%loseFightTime,leaveFight); %lose.schedule(%disarmTime,holsterWeapon); %win.holsterWeapon(); } function attack3_action(%win,%lose,%prefix) { if (%win.getState() $= "Dead" || %lose.getState() $= "Dead") return; %win.destroyThread(0); %lose.destroyThread(0); %win.setActionThread(%prefix @ "Winner"); %lose.setActionThread(%prefix @ "Loser"); playFightAudio(%win,AudioClosest3D,"fight3",%lose.getWorldBoxCenter()); } Quote Link to comment Share on other sites More sharing options...
Azaezel Posted March 14, 2017 Share Posted March 14, 2017 well... I can say quite a few script-exposed variables default to -1... If it's a case of the sucker getting referenced before it's set to a new value, that'd give you you that kind of output... Can't think of any 6-bit values used though with that... Quote Link to comment Share on other sites More sharing options...
Jason Campbell Posted March 14, 2017 Author Share Posted March 14, 2017 I can't figure out gdb debugger very well but I got a backtrace to show me shapebase.cpp or player.cpp is where the writeInt occurs.For a while I thought it was this.stream->writeInt(image.imageMountNode,6);It mounts attachments to weapons but a made it zero right before the writeInt so it always returned zero and it didn't do a thing.I just did a trace(1);And perhaps it's this. These lines are the last bunch. Must be in player or aiplayer. Entering AIPlayer::onCollision(23384, 23123) Leaving AIPlayer::onCollision() - return Leaving SpecOpsRifleman::onCollision() - return Entering SpecOpsRifleman::onCollision(699, 23123, 23384) Entering AIPlayer::onCollision(23123, 23384) Leaving AIPlayer::onCollision() - return Leaving SpecOpsRifleman::onCollision() - return Entering SpecOpsRifleman::onCollision(699, 23799, 21842) Entering AIPlayer::onCollision(23799, 21842) Leaving AIPlayer::onCollision() - return Leaving SpecOpsRifleman::onCollision() - return Entering SpecOpsRifleman::onCollision(699, 23799, 21514) Entering AIPlayer::onCollision(23799, 21514) Leaving AIPlayer::onCollision() - return Leaving SpecOpsRifleman::onCollision() - return Entering OpforRifleman::onCollision(700, 21514, 23799) Entering AIPlayer::onCollision(21514, 23799) Leaving AIPlayer::onCollision() - return Leaving OpforRifleman::onCollision() - return Entering OpforRifleman::onCollision(700, 21524, 21842) Entering AIPlayer::onCollision(21524, 21842) Leaving AIPlayer::onCollision() - return Leaving OpforRifleman::onCollision() - return Quote Link to comment Share on other sites More sharing options...
Jason Campbell Posted March 15, 2017 Author Share Posted March 15, 2017 Hey guys, the animation was screwed up for takedowns, Case sensitivity of Linux has made it tough to squash all the bugs. Anyway, I really thought that had done the trick but then the 7bit Fatal started again that I thought I had fixed. So I disabled the Fatal breakpoint in bitstream.cpp and played the example mission again and again. My memory usage was high but steady. Same usage as before (900MB with 16 AI) just seems quite a bit higher then the Windows version, which is Torque 3,5(460MB). I checked to see if it was a Linux thing and the Example FPS level from 3,10 is around 640MB when I added a NavMesh and some stock AI.Anyway, question is, what kind of trouble will I most likely run into by disabling the Fatal interrupt?Thanks Quote Link to comment Share on other sites More sharing options...
Azaezel Posted March 15, 2017 Share Posted March 15, 2017 You won't be catching uninitialized variables, out of range values, and subtle bugs of that nature. Certain extensions of the engine go particularly fatal there in incredibly non-obvious ways, beyond just 'well, lets go ahead and use the wrong value anyway'.. Quote Link to comment Share on other sites More sharing options...
Jason Campbell Posted March 15, 2017 Author Share Posted March 15, 2017 Okay, thanks. I will continue to attempt finding them. Quote Link to comment Share on other sites More sharing options...
Jason Campbell Posted March 18, 2017 Author Share Posted March 18, 2017 I've figured out the gdb debugger a little more and have been able to examine the backtrace frame by frame,, so I can find the exact line that caused the errors. Unfortunately, examining the local variables doesn't help much and every time I stop one, another pops up. Another thing, that -1/64 6 bit Fatal was not an Int, it was a Float name mRot, some sort of rotation calculation. After examining it, I realized that there was no real way to find out how it got to a -1 value. I used a real cheap method of catching it before it was written and checking if it was a negative number and if so, making it zero. I have no idea if that would make it worse? Also if it is a float, shouldn't it be -1.0? My c++ knowledge is limited.Strangely the actual AI is getting better as I figure out more, it seems to be better then the original Windows 3.5 version I had compiled without errors, subtle things. Makes me think that I had errors in that version that I didn't even know about. I've come so far, there is no way I'm giving up but it seems like a terrible game of wack-a-mole that never ends. I have another question. In your experience can TorqueScript errors throw an error into the c++ code? Reason I'm asking is, I'm concentrating so much on the source code but may be making it worse. Some of the TS errors may be caused by conflicts in the source code, I'm guessing, but should I attempt to remove all errors from the console then work on the source code?Thanks again. Quote Link to comment Share on other sites More sharing options...
Azaezel Posted March 18, 2017 Share Posted March 18, 2017 https://github.com/GarageGames/Torque3D/blob/c83efa59e0a11fc15c68afaf106807643191ac6f/Engine/source/core/stream/bitStream.cpp#L337-L347 first and last lines are why shoving a TS float value can trigger that. prolly does help verifiably isolate that down to a readFloat(&foo,6) in a packupdate or packdata then. fars TS errors goes, you'll recall that a .cs file will attempt to execute up to the point it hits a compilation flaw and stop there, so... pooooosssibly?With more data, sounds like I'd eyeballhttps://github.com/GarageGames/Torque3D/blob/7185d9664d7ee8c0469014acce9caad6d1380ea2/Engine/source/T3D/player.cpp#L6225-L6227+https://github.com/GarageGames/Torque3D/blob/7185d9664d7ee8c0469014acce9caad6d1380ea2/Engine/source/T3D/player.cpp#L6330-L6332 Quote Link to comment Share on other sites More sharing options...
Jason Campbell Posted March 19, 2017 Author Share Posted March 19, 2017 Well, you are right about the lines making the problem. It was this line, and it was a 7bit not the 6bit I talked about:https://github.com/GarageGames/Torque3D/blob/7185d9664d7ee8c0469014acce9caad6d1380ea2/Engine/source/T3D/player.cpp#L6225I don't understand really how to fix it.I wrote this stupid bit of code into it and it stopped the Fatal but honestly it can't be good. if ((mRot.z / M_2PI_F) < 0) { mRot.z = 0; } if ((mRot.z / M_2PI_F) >= 0) { stream->writeFloat(mRot.z / M_2PI_F, 7); } My newest error is being kicked off the server with a window telling me I don't have Full or access to some assets, I will write it down next time.I was wondering could this cause a problem, since Float isn't defined?https://github.com/GarageGames/Torque3D/blob/7185d9664d7ee8c0469014acce9caad6d1380ea2/Engine/source/T3D/player.cpp#L6080Thanks again Az Quote Link to comment Share on other sites More sharing options...
Azaezel Posted March 19, 2017 Share Posted March 19, 2017 Ok. so. Cliffsnotes on write, writefloat, writePacketData, and packUpdate1)write/read packetdata or pack/unpack update, (or, to be thorough pack/unpack Data are paired methods. meaning if it goes in in one form in one order in a write, it needs to come out in the exact same order, and in the exact same form in a read. Mismatching can lead to leakage, since it's literally decoding bits. (so if for instance you had write{bool a, float b} and read{float b, bool a}, you'd actually be getting the true/false tacked on to float b and it's last bit thrown over to bool a in the read. common cause of 'hey this data went corrupt' aka 'These Aren't The Datablocks You're Looking For'}2) in order of frequency run:A) packData/unpackData: done once on loading a mission. these are your datablock setters/getters.B) writePacketData/readPacketData: sent to every client in scope (scope gets a bit complex for a quick primer, so we'll skip that)C) packUpdate/unpackUpdate: sent to a given controlled client alone. So stuff like personal energy level. (forget offhand if that's set to update at a higher rate than the PacketData pair.3)straight write() / read() calls use the full 32 bits in a float. (Basically uses a sizeof() lookup) while writefloat lets you specify the size you're using in a lossy manner. why it's generally a Bad Thing to go lower than 6ish, and can conversely add up pretty bad if you just run with 32s.That help any? Quote Link to comment Share on other sites More sharing options...
Jason Campbell Posted March 21, 2017 Author Share Posted March 21, 2017 Thank you for the primer Azaezel,edit: Thought I had it, I was wrong.Just a note: Any Linux user who needs to merge code, Meld is a Godsend. I can't believe the ease of it and what ever formula they use to figure where code goes, is amazing. 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.