From 90bb6175dc0fc9a06cb533a7b22fad5bce552de1 Mon Sep 17 00:00:00 2001 From: ChocoTaco Date: Sat, 11 Jan 2025 11:51:32 -0500 Subject: [PATCH] Update flagTunnelingFix.cs --- Classic/scripts/autoexec/flagTunnelingFix.cs | 508 +++++++++++++------ 1 file changed, 341 insertions(+), 167 deletions(-) diff --git a/Classic/scripts/autoexec/flagTunnelingFix.cs b/Classic/scripts/autoexec/flagTunnelingFix.cs index 2afb8d8..3a1d66b 100644 --- a/Classic/scripts/autoexec/flagTunnelingFix.cs +++ b/Classic/scripts/autoexec/flagTunnelingFix.cs @@ -1,171 +1,108 @@ -//Fixes for collision tunneling among other flag issues, note only works in classic ctf game types +//Fixes for collision tunneling and other issues, note only tested in classic //Script By:DarkTiger -//V2.1 +//v3.4 switch over to using SAT/OBB for hitbox detection accuracy, also heavy optimizations becuase of this change +//v3.3 - fixed ceiling deadstoping,fixed wall and ceiling tunneling $antiObjTunnel +//V3.2 - script refactor, removed flag sim in favor of just an offset on toss + $ftEnable = 1;//disables all $limitFlagCalls = 1; // prevents frame perfect events witch can cause bad outcomes $antiCeiling = 1; // note this is auto enabled with $boxStuckFix as it needs to check for this -$antiTerTunnel = 0;//prevents terrain tunneling keeps the flag above the terrain leave this off unless you think its a problem +$antiObjTunnel = 0;//prevents terrain and interior tunneling more thigns can be added see first part of DefaultGame::flagColTest $antiFlagImpluse = 1000;//time out period to prevent explosions from effecting flags on drop/toss -$boxStuckFix = 1; + +$boxStuckFix = 1;// enables flag offset, spawns the flag outside of the player to keep it from getting stuck +$flagOffset = 1;// how far to offset the flag 1m seems like it works 90% of the time + +// adds initial update to setVelocity and setTransform to updates its parameters across clients +//enable $flagResetTime with setting it to 5000 if you disable a mempatch + +//expermental flag static fix +//memPatch("60456c","11000018");//transform +memPatch("6040ff","01"); //setVelocity +$flagResetTime = 0;// 1000-5000 if you want this feature enabled, resets flag to stand in case of desync should not be needed //best to leave these values alone unless you understand what the code is doing -$flagSimTime = 60;//note a higher the time, the larger the sweep scans will be +$flagSimTime = 64;//note a higher the time, the larger the sweep scans will be $flagCheckRadius = 50; -$playerBoxA = "-0.6 -0.6 0"; -$playerBoxB = "0.6 0.6 2.3"; -$flagStuckTime = 1000; +$playerSizeBox = "1.2 1.2 2.3"; +$flagBoxSize = "0.796666 0.139717 2.46029"; -$flagSimRate = 30; -$tickDelay = 1; //delay the sim by 1 ticks in case its not needed - - -function flagSim(%flag,%player){ - %bypassBoxCheck = 0;// debug sim - //%mass = 80;// not needed - %bounceFriction = 0.6; - %bounceElasticity = 0.2; - %drag = 0.5; - %simRate = $flagSimRate; - %timeFrame = mFloor(1000 / %simRate); - %dt = %timeFrame / 1000; - %Box2 = %flag.getWorldBox(); - %Box1 = %player.getWorldBox(); - if(!%flag.isHome && !isObject(%flag.carrier)){ - if((boxIntersect(%Box1, %Box2) || %bypassBoxCheck) && vectorLen(%flag.finalVel) > 1 && %flag.countsim < 32){ - %flag.setVelocity("0 0 0");// keep it zeroed out - %xform = %flag.getTransform(); - %oldPos = getWords(%xform,0,2);// we dont use lastSimPos here as it will be fighting the engine too much instead we use it in the raycast - %flag.finalVel = vectorAdd(%flag.finalVel, "0 0" SPC (getGravity() * 1) * %dt);// engine adds its gravity so... prob not needed - %flag.finalVel = vectorSub(%flag.finalVel, vectorScale(%flag.finalVel, %drag * %dt)); - %newPos = vectorAdd(%oldPos, vectorScale(%flag.finalVel,%dt)); - - %mask = $TypeMasks::InteriorObjectType | $TypeMasks::StaticTSObjectType | $TypeMasks::TerrainObjectType;//$TypeMasks::ForceFieldObjectType - %movRayB = containerRayCast(%flag.lastSimPos, %newPos, %mask, %flag); - %movRayT = containerRayCast(vectorAdd(%flag.lastSimPos,"0 0 2.4"), vectorAdd(%newPos,"0 0 2.4"), %mask, %flag); - - if(%movRayB){ - %hitRay = %movRayB; - } - if(%movRayT){ - %hitRay = getWord(%movRayT,0) SPC %oldPos SPC getWords(%movRayT,4,6); - } - - if(%hitRay){ - %normal = getWords(%hitRay, 4, 6); - // Reflect the velocity around the surface normal - %reflectedVel = vectorSub(%flag.finalVel, vectorScale(%normal, vectorDot(%flag.finalVel, %normal) * 2.0)); - // Calculate the tangent component for surface friction - %tangent = vectorSub(%reflectedVel, vectorScale(%normal, vectorDot(%reflectedVel, %normal))); - // Apply surface friction - %bounceVel = vectorSub(%reflectedVel, vectorScale(%tangent, %bounceFriction)); - // Apply elasticity to modulate the speed of the bounce - %flag.finalVel = vectorScale(%bounceVel, %bounceElasticity); - // Adjust the new position to the point of impact plus a small offset along the normal - %newPos = vectorAdd(getWords(%hitRay, 1, 3), vectorScale(%normal, 0.05)); - } - %flag.lastSimPos = %newPos;// we do this so theres no gaps in are sim other wise it could end up underground - %flag.setTransform(%newPos SPC getWords(%xform,3,6)); - //%flag.setVelocity(%flag.finalVel); - %flag.countsim++; - schedule(%timeFrame,0,"flagSim",%flag,%player); - } - else{ - //error("simCount" SPC %flag.countsim SPC vectorLen(%flag.finalVel)); - if(vectorLen(%flag.finalVel) && %flag.countsim > 0){ - %flag.setVelocity(%flag.finalVel); - } - } - } -} - -function delayStartFlag(%obj,%this){ - %obj.countsim = 0; - %obj.lastSimPos = %obj.getPosition(); - %drag = 0.5; - %dt = mFloor(1000 / $flagSimRate) / 1000; - for(%i = 0; %i < $tickDelay; %i++){ - %obj.finalVel = vectorSub(%obj.finalVel, vectorScale(%obj.finalVel, %drag * %dt)); - } - flagSim(%obj,%this); -} +//0 = old AABB method uses fixed box size makes the player bit narrow +//1 = new OBB method uses perfect box intersection +//2 = AABB method but uses boundbox can make the player larger then it is given there direction +//3 = AABB fixed sizes uses $playerSizeBox and $flagBoxSize to do the box checking +$boxCollision = 1;// off is the old AABB method aka the old method +$flagColBypass = 0;//bypass all other collision methods other then this one package flagFix{ + //because the fade is 2000ms we can compensate the delayed reset not to mess with client timers + function Flag::onCollision(%data,%obj,%col){ + if(!$flagColBypass){ + parent::onCollision(%data,%obj,%col); + } + } + function ShapeBase::throwObject(%this,%obj){ parent::throwObject(%this,%obj); %data = %obj.getDatablock(); - if(%data.getName() $= "Flag"){ - %fpos = %obj.getPosition(); + if($ftEnable && %data.getName() $= "Flag"){ + %tpos = %obj.getTransform(); + %fpos = getWords(%tpos,0, 2); + %obj.dtLastPos = %fpos; + %vel = %obj.getVelocity(); + %posOffset = VectorAdd(%fpos, VectorScale(VectorNormalize(%vel), 2)); - if($boxStuckFix){ - %obj.finalVel = %obj.getVelocity(); - %upRay = containerRayCast(vectorAdd(%fpos,"0 0 0.1"), vectorAdd(%fpos,"0 0 2.5"), $TypeMasks::InteriorObjectType | $TypeMasks::StaticTSObjectType | $TypeMasks::ForceFieldObjectType, %obj); - if(%upRay){ - %dist = vectorDist(%fpos,getWords(%upRay,1,3)); - %obj.setTransform(vectorSub(%fpos,"0 0" SPC (2.6 - %dist)) SPC getWords(%obj.getTransform(), 3, 6)); - error("Ceiling" SPC %dist); - } - %wallRay = containerRayCast(%fpos, VectorAdd(%fpos, VectorScale(%this.getForwardVector(), 2)), $TypeMasks::InteriorObjectType | $TypeMasks::StaticTSObjectType | $TypeMasks::ForceFieldObjectType, %obj); - if(!%wallRay){ - schedule($tickDelay * mFloor(1000 / $flagSimRate),0,"delayStartFlag",%obj,%this); - } - } - else if($antiCeiling){ + if($antiCeiling){//flag height 2.46029 //0.1 offset any fp errors with the flag position being at ground level, 2.4 offset flag height offset + some extra %upRay = containerRayCast(vectorAdd(%fpos,"0 0 0.1"), vectorAdd(%fpos,"0 0 2.5"), $TypeMasks::InteriorObjectType | $TypeMasks::StaticTSObjectType | $TypeMasks::ForceFieldObjectType, %obj); if(%upRay){ - %dist = vectorDist(%fpos,getWords(%upRay,1,3)); - %obj.setTransform(vectorSub(%fpos,"0 0" SPC (2.6 - %dist)) SPC getWords(%obj.getTransform(), 3, 6)); - //error("bump2"); + %obj.setTransform(vectorSub(%this.getPosition(),"0 0" SPC 0.3) SPC getWords(%this.getTransform(),3,6)); + %obj.setVelocity(getWords(%vel,0,1) SPC 0); } } - } - } + if($boxStuckFix && !%upRay){ + %wallMask = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::StaticObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::VehicleObjectType; + %wallRay = containerRayCast(%fpos, %posOffset, %wallMask, %obj); - function CTFGame::startFlagCollisionSearch(%game, %flag){ - parent::startFlagCollisionSearch(%game, %flag); - if((getSimTime() - %game.fcs) >= $flagSimTime && $ftEnable){ - %game.flagColTest(%flag); - %game.fcs = getSimTime(); - } - } - function SCtFGame::startFlagCollisionSearch(%game, %flag){ - parent::startFlagCollisionSearch(%game, %flag); - if((getSimTime() - %game.fcs) >= $flagSimTime && $ftEnable){ - %game.flagColTest(%flag); - %game.fcs = getSimTime(); - } - } + %fwoPos = VectorAdd(%fpos, VectorScale(VectorNormalize(%vel), $flagOffset)); - function PracticeCTFGame::startFlagCollisionSearch(%game, %flag){ - parent::startFlagCollisionSearch(%game, %flag); - if((getSimTime() - %game.fcs) >= $flagSimTime && $ftEnable){ - %game.flagColTest(%flag); - %game.fcs = getSimTime(); + %upRay = containerRayCast(vectorAdd(%fwoPos,"0 0 0.1"), vectorAdd(%fwoPos,"0 0 2.5"), $TypeMasks::InteriorObjectType | $TypeMasks::StaticTSObjectType | $TypeMasks::ForceFieldObjectType, %obj); + + if(!%wallRay){// make sure we dont end up in a wall + if(!%upRay){ + %obj.setTransform(%fwoPos SPC getWords(%this.getTransform(),3,6)); + %obj.dtLastPos = %fwoPos; + } + } + } } } function CTFGame::startMatch(%game){ parent::startMatch(%game); if(!isEventPending(Game.flagLoop)){ + $TeamFlag[1].resetTime = 0; + $TeamFlag[2].resetTime = 0; %game.atHomeFlagLoop(); } - %game.fcs = getSimTime(); } function SCtFGame::startMatch(%game){ parent::startMatch(%game); if(!isEventPending(Game.flagLoop)){ + $TeamFlag[1].resetTime = 0; + $TeamFlag[2].resetTime = 0; %game.atHomeFlagLoop(); } - %game.fcs = getSimTime(); } function PracticeCTFGame::startMatch(%game){ parent::startMatch(%game); if(!isEventPending(Game.flagLoop)){ + $TeamFlag[1].resetTime = 0; + $TeamFlag[2].resetTime = 0; %game.atHomeFlagLoop(); } - %game.fcs = getSimTime(); } //prevents frame perfect flag touches witch can cause bad stuff to happen in ctf @@ -222,8 +159,7 @@ package flagFix{ function Flag::shouldApplyImpulse(%data, %obj){ %val = parent::shouldApplyImpulse(%data, %obj); - //error("meow"); - if($antiFlagImpluse > 0 && %val && %obj.lastDropTime > 0){ + if(%val && $antiFlagImpluse > 0 && %obj.lastDropTime > 0){ %time = getSimTime() - %obj.lastDropTime; if(%time < $antiFlagImpluse){ %val = 0; @@ -233,38 +169,151 @@ package flagFix{ } }; activatePackage(flagFix); -function DefaultGame::flagColTest(%game, %flag){ -//flag ceiling check - %curPos = %flag.getWorldBoxCenter(); - if( !%flag.isHome ){ - if($antiTerTunnel){ - // anti flag tunneling on terrain - if(%flag.lastUpdate > 0 && (getSimTime() - %flag.lastUpdate) < 128){//make sure are last position is current - %terRay = containerRayCast(%flag.dtLastPos, %curPos, $TypeMasks::TerrainObjectType, %flag); - if(%terRay){ - %curPos = vectorAdd(getWords(%terRay,1,3), "0 0 0.5"); - %flag.setTransform(%curPos SPC getWords(%flag.getTransform(), 3, 6)); + +function FlagCollision(%data,%obj,%col){ + if($flagColBypass){ + if (%col.getDataBlock().className $= Armor) + { + if (%col.isMounted()) + return; + + // z0dd - ZOD, 6/13/02. Touch the flag and your invincibility and cloaking goes away. + if(%col.station $= "" && %col.isCloaked()) + { + if( %col.respawnCloakThread !$= "" ) + { + Cancel(%col.respawnCloakThread); + %col.setCloaked( false ); + %col.respawnCloakThread = ""; } } - %flag.lastUpdate = getSimTime(); - %flag.dtLastPos = %curPos; + if( %col.client > 0 ) + { + %col.setInvincibleMode(0, 0.00); + %col.setInvincible( false ); + } + + // a player hit the flag + Game.playerTouchFlag(%col, %obj); + } + } + else{ + %data.onCollision(%flag, %player); + } +} + +function vectorMul(%a,%b){ + %x = getWords(%a,0) * getWords(%b,0); + %y = getWords(%a,1) * getWords(%b,1); + %z = getWords(%a,2) * getWords(%b,2); + return %x SPC %y SPC %z; +} + +function generateBoxData(){ + + %playerSize = $playerSizeBox; //"1.2 1.2 2.3"; + %halfSize = vectorMul(%playerSize, "0.5 0.5 0"); + $plrBoxMin = %minA = VectorSub("0 0 0", %halfSize); + $plrBoxMax = %maxA = getWords(%halfSize,0,1) SPC getWord(%playerSize,2); + $plrBox = %minA SPC %maxA; + %vSubA = vectorSub(%maxA, %minA); + + %flagSize = $flagBoxSize; + %halfSize = vectorMul(%flagSize, "0.5 0.5 0"); + $flagBoxMin = %minB = VectorSub("0 0 -0.1", %halfSize); + $flagBoxMax = %maxB = getWords(%halfSize,0,1) SPC getWord(%flagSize,2); + $flagBox = %minB SPC %maxB; + %vSubB = vectorSub(%maxB, %minB); + + %box[0] = "0 0 0"; + %box[1] = "1 0 0"; + %box[2] = "0 1 0"; + %box[3] = "1 1 0"; + %box[4] = "0 0 1"; + %box[5] = "1 0 1"; + %box[6] = "0 1 1"; + %box[7] = "1 1 1"; + + for(%i = 0; %i < 8; %i++){ + $playerBoxData[%i] = vectorAdd(%minA, vectorMul(%vSubA, %box[%i])); + $flagBoxData[%i] = vectorAdd(%minB, vectorMul(%vSubB, %box[%i])); + } + +}generateBoxData(); + +function vectorLerp(%point1, %point2, %t) { + return vectorAdd(%point1, vectorScale(vectorSub(%point2, %point1), %t)); +} + +function boxIntersectAABB(%plr, %flg, %lerpPos){ + if($boxCollision == 2){ + %a = %plr.getWorldBox(); + %b = %flg.getWorldBox(); + } + else if($boxCollision == 3){ + %fpos = %flg.getPosition(); + + %a = vectorAdd($plrBoxMin, %lerpPos) SPC vectorAdd($plrBoxMax, %lerpPos); + %b = vectorAdd($flagBoxMin, %fpos) SPC vectorAdd($flagBoxMax, %fpos); + } + else{ + %plrMinMax = %plr.getObjectBox(); + %a = vectorAdd(getWords(%plrMinMax,0,2), %lerpPos) SPC vectorAdd(getWords(%plrMinMax,3,5), %lerpPos); + %b = %flg.getWorldBox(); + } + + return (getWord(%a, 0) <= getWord(%b, 3) && getWord(%a, 3) >= getWord(%b, 0)) && + (getWord(%a, 1) <= getWord(%b, 4) && getWord(%a, 4) >= getWord(%b, 1)) && + (getWord(%a, 2)<= getWord(%b, 5) && getWord(%a, 5) >= getWord(%b, 2)); +} + +function DefaultGame::flagColTest(%game, %flag, %rsTeam, %ext){ +//////////////////////////////////////////////////////////////////////////////// +//obj tunneling check + %flagPos = %flag.getPosition(); + if(!%flag.isHome && $antiObjTunnel){ + %fOffset =vectorAdd(%flagPos,"0 0 0.1"); + %dist = vectorDist(%flag.dtLastPos, %fOffset); + if(%dist > 2.5){//2.5 is the rough flag height + %wallMask = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType; + %terRay = containerRayCast(%flag.dtLastPos, %fOffset, %wallMask, %flag); + if(%terRay){ + %flag.setTransform(%flag.dtLastPos SPC getWords(%flag.getTransform(), 3, 6)); + } + else{ + %flag.dtLastPos = %fOffset; + } } } //////////////////////////////////////////////////////////////////////////////// //flag collision check - %Box2 = %flag.getWorldBox(); - InitContainerRadiusSearch( %curPos, $flagCheckRadius, $TypeMasks::PlayerObjectType); + InitContainerRadiusSearch( %flagPos, $flagCheckRadius, $TypeMasks::PlayerObjectType); while((%player = containerSearchNext()) != 0){ %playerPos = %player.getPosition(); - if(%player.lastSim > 0 && (%player.getState() !$= "Dead")){// only check at speed - if((getSimTime() - %player.lastSim) <= 128){//make sure are last position is valid - %sweepCount = mFloor(vectorDist(%playerPos, %player.oldPos) + 1); - for(%i = 0; %i < %sweepCount; %i++){// sweep behind us to see if we should have hit something - %lerpPos = vectorLerp(%playerPos, %player.oldPos, (%i+1)/%sweepCount);//back sweep - %Box1 = vectorAdd($playerBoxA, %lerpPos) SPC vectorAdd($playerBoxB, %lerpPos); - if(boxIntersect(%Box1, %Box2)){ - %flag.getDataBlock().onCollision(%flag, %player); - break; + if((%rsTeam && %flag.team != %player.team) || !%rsTeam || %player == %ext){ + %flagDist = vectorDist(%flagPos, %playerPos); + if(%player.lastSim > 0 && (%player.getState() !$= "Dead")){// only check at speed + //%fdot = vectorDot(vectorNormalize(%player.getVelocity()),vectorNormalize(VectorSub(%flagPos, %playerPos))); + // %tickDist = vectorLen(%player.getVelocity()) * ($flagSimTime/1000); + %sweepCount = mFloor(vectorDist(%playerPos, %player.oldPos) + 1.5); + if((getSimTime() - %player.lastSim) <= 128 && %flagDist-2 < %sweepCount){//make sure are last position is valid + //error(%player SPC %flagDist SPC %sweepCount); + for(%i = 0; %i < %sweepCount; %i++){// sweep behind us to see if we should have hit something + %lerpPos = vectorLerp(%playerPos, %player.oldPos, %i/(%sweepCount-1));//back sweep + if($boxCollision == 1){ + if(boxIntersect(%player, %flag, %lerpPos)){ + //error("flag hit"); + FlagCollision(%flag.getDataBlock(),%flag, %player); + break; + } + } + else{ + if(boxIntersectAABB(%player, %flag, %lerpPos)){ + //error("flag hit"); + FlagCollision(%flag.getDataBlock(),%flag, %player); + break; + } + } } } } @@ -272,26 +321,151 @@ function DefaultGame::flagColTest(%game, %flag){ %player.oldPos = %playerPos; %player.lastSim = getSimTime(); } -} - -function vectorLerp(%point1, %point2, %t) { - return vectorAdd(%point1, vectorScale(vectorSub(%point2, %point1), %t)); -} - -function boxIntersect(%a, %b){ - return (getWord(%a, 0) <= getWord(%b, 3) && getWord(%a, 3) >= getWord(%b, 0)) && - (getWord(%a, 1) <= getWord(%b, 4) && getWord(%a, 4) >= getWord(%b, 1)) && - (getWord(%a, 2) <= getWord(%b, 5) && getWord(%a, 5) >= getWord(%b, 2)); + //error("scan count" SPC %scanCount SPC %scanPlrCount); } function DefaultGame::atHomeFlagLoop(%game){ - if($TeamFlag[1].isHome ){ - %game.flagColTest($TeamFlag[1], 0); + if(isObject($TeamFlag[1]) && isObject($TeamFlag[2])){ + if($flagResetTime > 0){ + if(%game.flagResetTime > $flagResetTime){ + if($TeamFlag[1].isHome){ + $TeamFlag[1].setTransform($TeamFlag[1].originalPosition); + } + if($TeamFlag[2].isHome){ + $TeamFlag[2].setTransform($TeamFlag[2].originalPosition); + } + %game.flagResetTime = 0; + } + %game.flagResetTime += $flagSimTime; + } + + if($TeamFlag[1].isHome && $TeamFlag[2].isHome){//11 + %game.flagColTest($TeamFlag[1],1,0);// only look at the other team + %game.flagColTest($TeamFlag[2],1,0);// only look at the other team + } + else if(!$TeamFlag[1].isHome && $TeamFlag[2].isHome){//01 + if(isObject($TeamFlag[1].carrier)){// flag has been dropped + %game.flagColTest($TeamFlag[2],1, $TeamFlag[1].carrier); //scan for other team expect for are carrier + } + else{ + %game.flagColTest($TeamFlag[1],0,0);// scan for everyone can touch it + %game.flagColTest($TeamFlag[2],1,0);// team 2 flag is still at home so only scan for the other team + } + } + else if($TeamFlag[1].isHome && !$TeamFlag[2].isHome){//10 + if(isObject($TeamFlag[2].carrier)){// flag has been dropped + %game.flagColTest($TeamFlag[1],1, $TeamFlag[2].carrier); //scan for other team expect for are carrier + } + else{ + %game.flagColTest($TeamFlag[1],1,0);// team 1 flag is still at home so only scan for the other team + %game.flagColTest($TeamFlag[2],0,0);// scan for everyone can touch it + } + } + else if(!$TeamFlag[1].isHome && !$TeamFlag[2].isHome){//00 + if(!isObject($TeamFlag[1].carrier)){// flag has been dropped + %game.flagColTest($TeamFlag[1],0,0);// scan for everyone can touch it + } + if(!isObject($TeamFlag[2].carrier)){// flag has been dropped + %game.flagColTest($TeamFlag[2],0,0);// scan for everyone can touch it + } + } } - if($TeamFlag[2].isHome){ - %game.flagColTest($TeamFlag[2], 0); - } - %speed = ($HostGamePlayerCount - $HostGameBotCount > 0) ? $flagSimTime : 30000; - if(isObject(Game) && $missionRunning && $ftEnable) + if(isObject(Game) && $ftEnable){ + %speed = ($HostGamePlayerCount - $HostGameBotCount > 0) ? $flagSimTime : 30000; %game.flagLoop = %game.schedule(%speed, "atHomeFlagLoop"); + } +} + +function boxIntersect(%objA, %objB, %scanPos) { + // Retrieve the 8 corners of the box for both objects + %matrixA = %objA.getTransform(); + if(getWordCount(%scanPos)){// need to check a postion other then default + %matrixA = %scanPos SPC getWords(%matrixA,3,6); + } + %matrixB = %objB.getTransform(); + + + %cornerA[0] = MatrixMulPoint(%matrixA, "-0.6 -0.6 0"); + %cornerA[1] = MatrixMulPoint(%matrixA, "0.6 -0.6 0"); + %cornerA[2] = MatrixMulPoint(%matrixA, "-0.6 0.6 0"); + %cornerA[3] = MatrixMulPoint(%matrixA, "0.6 0.6 0"); + + %cornerA[4] = MatrixMulPoint(%matrixA, "-0.6 -0.6 2.3"); + %cornerA[5] = MatrixMulPoint(%matrixA, "0.6 -0.6 2.3"); + %cornerA[6] = MatrixMulPoint(%matrixA, "-0.6 0.6 2.3"); + %cornerA[7] = MatrixMulPoint(%matrixA, "0.6 0.6 2.3"); + + + %cornerB[0] = MatrixMulPoint(%matrixB, "-0.398333 -0.0698583 -0.1"); + %cornerB[1] = MatrixMulPoint(%matrixB, "0.398333 -0.0698583 -0.1"); + %cornerB[2] = MatrixMulPoint(%matrixB, "-0.398333 0.0698587 -0.1"); + %cornerB[3] = MatrixMulPoint(%matrixB, "0.398333 0.0698587 -0.1"); + + %cornerB[4] = MatrixMulPoint(%matrixB, "-0.398333 -0.0698583 2.46029"); + %cornerB[5] = MatrixMulPoint(%matrixB, "0.398333 -0.0698583 2.46029"); + %cornerB[6] = MatrixMulPoint(%matrixB, "-0.398333 0.0698587 2.46029"); + %cornerB[7] = MatrixMulPoint(%matrixB, "0.398333 0.0698587 2.46029"); + + // Define the axes to test (these are the edges of both boxes) + %ax[0] = vectorNormalize(vectorSub(%cornerA[1], %cornerA[0]));//X cross forward and up + %ax[1] = vectorNormalize(vectorSub(%cornerA[2], %cornerA[0]));//Y forward vector + %ax[2] = "0 0 1"; + + %ax[3] = vectorNormalize(vectorSub(%cornerB[1], %cornerB[0]));//X cross forward and up + %ax[4] = vectorNormalize(vectorSub(%cornerB[2], %cornerB[0])); //Y forward vector + %ax[5] = "0 0 1"; + + + // For each axis + for (%i = 0; %i < 6; %i++) { + %axis = %ax[%i]; + + // Project each corner of box A onto the axis + %minProjA = vectorDot(%cornerA[0], %axis); + %maxProjA = %minProjA; + + for (%j = 1; %j < 8; %j++) { + %projA = vectorDot(%cornerA[%j], %axis); + + %minProjA = (%projA < %minProjA) ? %projA : %minProjA; + %maxProjA = (%projA > %maxProjA) ? %projA : %maxProjA; + } + + // Project each corner of box B onto the axis + %minProjB = vectorDot(%cornerB[0], %axis); + %maxProjB = %minProjB; + + for (%j = 1; %j < 8; %j++) { + %projB = vectorDot(%cornerB[%j], %axis); + %minProjB = (%projB < %minProjB) ? %projB : %minProjB; + %maxProjB = (%projB > %maxProjB) ? %projB : %maxProjB; + } + + // Check for overlap + if (%maxProjA < %minProjB || %maxProjB < %minProjA) { + return false; // No overlap on this axis, boxes do not intersect + } + } + + return true; // Overlap on all axes, boxes intersect +} + +function colFlagTest(){ + %conObj = LocalClientConnection.player; //LocalClientConnection.getControlObject(); + %flag1 = boxIntersect(%conObj,$TeamFlag[1]); + %flag2 = boxIntersect(%conObj,$TeamFlag[2]); + + %flag1AABB = boxIntersectAABB(%conObj, $TeamFlag[1], %conObj.getPosition()); + %flag2AABB = boxIntersectAABB(%conObj, $TeamFlag[2], %conObj.getPosition()); + + error("test" SPC "Flag 1" SPC %flag1 SPC "Flag 2" SPC %flag2); + error("test" SPC "Flag 1A" SPC %flag1AABB SPC "Flag 2A" SPC %flag2AABB); + bottomprint(%conObj.client, "FlagS" SPC %flag1 SPC "FlagI" SPC %flag2 SPC "FlagS AABB" SPC %flag1AABB SPC "FlagI AABB" SPC %flag2AABB, 5, 1); +} + +function testFlagSpeed(%speed){ + %player = LocalClientConnection.player; + %fvec = %player.getForwardVector(); + %vel = vectorScale(%fvec,%speed); + %player.setVelocity(%vel); } \ No newline at end of file