Update flagTunnelingFix.cs

This commit is contained in:
ChocoTaco 2025-01-11 11:51:32 -05:00
parent 5be702178d
commit 90bb6175dc

View file

@ -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);
}