From 7ee1d7eedbf597d317354988c340f9137bc86d9f Mon Sep 17 00:00:00 2001 From: ChocoTaco Date: Sat, 19 Oct 2024 15:10:31 -0400 Subject: [PATCH] Update flagTunnelingFix.cs --- Classic/scripts/autoexec/flagTunnelingFix.cs | 183 +++++++++++++------ 1 file changed, 129 insertions(+), 54 deletions(-) diff --git a/Classic/scripts/autoexec/flagTunnelingFix.cs b/Classic/scripts/autoexec/flagTunnelingFix.cs index 959d25f..2afb8d8 100644 --- a/Classic/scripts/autoexec/flagTunnelingFix.cs +++ b/Classic/scripts/autoexec/flagTunnelingFix.cs @@ -1,19 +1,126 @@ //Fixes for collision tunneling among other flag issues, note only works in classic ctf game types //Script By:DarkTiger -$ftEnable = 1;//disables all +//V2.1 +$ftEnable = 1;//disables all $limitFlagCalls = 1; // prevents frame perfect events witch can cause bad outcomes -$antiCeiling = 1; // keep flags from getting stuck in the ceiling -$antiTerTunnel = 0;//prevents terrain tunneling keeps the flag above the terrain leave this off unless you think its a problem +$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 $antiFlagImpluse = 1000;//time out period to prevent explosions from effecting flags on drop/toss +$boxStuckFix = 1; - -//best to leave these values alone unless you understand what the code is doing +//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 $flagCheckRadius = 50; $playerBoxA = "-0.6 -0.6 0"; $playerBoxB = "0.6 0.6 2.3"; -$flagStuckTime = 1000; +$flagStuckTime = 1000; + +$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); +} + package flagFix{ + function ShapeBase::throwObject(%this,%obj){ + parent::throwObject(%this,%obj); + %data = %obj.getDatablock(); + if(%data.getName() $= "Flag"){ + %fpos = %obj.getPosition(); + + 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){ + //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"); + } + } + } + } + function CTFGame::startFlagCollisionSearch(%game, %flag){ parent::startFlagCollisionSearch(%game, %flag); if((getSimTime() - %game.fcs) >= $flagSimTime && $ftEnable){ @@ -65,89 +172,73 @@ package flagFix{ function CTFGame::playerTouchFlag(%game, %player, %flag){ if(%flag.lastFlagCallms > 0 && $limitFlagCalls){ %timeDif = getSimTime() - %flag.lastFlagCallms; - if(%timeDif < 32){ - return; + if(%timeDif < 32){ + return; } } %flag.lastFlagCallms = getSimTime(); parent::playerTouchFlag(%game, %player, %flag); } - + function SCtFGame::playerTouchFlag(%game, %player, %flag){ if(%flag.lastFlagCallms > 0 && $limitFlagCalls){ %timeDif = getSimTime() - %flag.lastFlagCallms; if(%timeDif < 32){ - return; + return; } } %flag.lastFlagCallms = getSimTime(); parent::playerTouchFlag(%game, %player, %flag); } - + function PracticeCTFGame::playerTouchFlag(%game, %player, %flag){ if(%flag.lastFlagCallms > 0 && $limitFlagCalls){ %timeDif = getSimTime() - %flag.lastFlagCallms; if(%timeDif < 32){ - return; + return; } } %flag.lastFlagCallms = getSimTime(); parent::playerTouchFlag(%game, %player, %flag); } - + function CTFGame::playerDroppedFlag(%game, %player){ %flag = %player.holdingFlag; %flag.lastDropTime = getSimTime(); parent::playerDroppedFlag(%game, %player); } - + function SCtFGame::playerDroppedFlag(%game, %player){ %flag = %player.holdingFlag; %flag.lastDropTime = getSimTime(); parent::playerDroppedFlag(%game, %player); } - + function PracticeCTFGame::playerDroppedFlag(%game, %player){ %flag = %player.holdingFlag; %flag.lastDropTime = getSimTime(); parent::playerDroppedFlag(%game, %player); } - + function Flag::shouldApplyImpulse(%data, %obj){ - %val = parent::shouldApplyImpulse(%data, %obj); + %val = parent::shouldApplyImpulse(%data, %obj); + //error("meow"); if($antiFlagImpluse > 0 && %val && %obj.lastDropTime > 0){ %time = getSimTime() - %obj.lastDropTime; if(%time < $antiFlagImpluse){ - %val = 0; + %val = 0; } } return %val; } }; activatePackage(flagFix); - - function DefaultGame::flagColTest(%game, %flag){ //flag ceiling check %curPos = %flag.getWorldBoxCenter(); if( !%flag.isHome ){ - if($antiCeiling){ - %flag.stuckChkTimer += $flagSimTime; - if(%flag.stuckChkTimer > $flagStuckTime){ // rate limit are checks - if(vectorLen(%flag.getVelocity()) < 2){ // only check if we are not at speed - %fpos = %flag.getPosition(); - //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.4"), $TypeMasks::InteriorObjectType | $TypeMasks::StaticTSObjectType | $TypeMasks::ForceFieldObjectType, %flag); - if(%upRay){ - %dist = vectorDist(%fpos,getWords(%upRay,1,3)); - %flag.setTransform(vectorSub(%fpos,"0 0" SPC (2.5 - %dist)) SPC getWords(%flag.getTransform(), 3, 6)); - } - } - %flag.stuckChkTimer = 0; - } - } if($antiTerTunnel){ - // anti flag tunneling on terrain + // 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){ @@ -181,7 +272,7 @@ function DefaultGame::flagColTest(%game, %flag){ %player.oldPos = %playerPos; %player.lastSim = getSimTime(); } -} +} function vectorLerp(%point1, %point2, %t) { return vectorAdd(%point1, vectorScale(vectorSub(%point2, %point1), %t)); @@ -203,20 +294,4 @@ function DefaultGame::atHomeFlagLoop(%game){ %speed = ($HostGamePlayerCount - $HostGameBotCount > 0) ? $flagSimTime : 30000; if(isObject(Game) && $missionRunning && $ftEnable) %game.flagLoop = %game.schedule(%speed, "atHomeFlagLoop"); -} - - - - -//original flag impluse fix -//dont use this function, it likes to ue im leaving this here just as a reminder -//also note flag gains velocity from things when not in play aka at stand or on a player backs -//if this is ever used that built up velocity needs to be zeroed out when it not in play -//function Item::applyImpulse(%this, %position, %impulseVec){ - //%data = %this.getDatablock(); - //%x = getWord(%impulseVec, 0) / %data.mass; - //%y = getWord(%impulseVec, 1) / %data.mass; - //%z = getWord(%impulseVec, 2) / %data.mass; - //%vel = %x SPC %y SPC %z; - //%this.setVelocity(vectorAdd(%this.getVelocity(), %vel)); -//} +} \ No newline at end of file