Skip to navigation

Gameplay: CheckEnemyGaze (Part 2 of 2)

Name: CheckEnemyGaze (Part 2 of 2) [Show more] Type: Subroutine Category: Gameplay Summary: Calculate whether the current enemy can see the specified object
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
LDA enemyViewingArc \ Set T = enemyViewingArc / 2 LSR A \ STA T \ So T is the yaw width of half the enemy's viewing arc, \ which is always 10 as enemyViewingArc is only ever set \ to 20 LDA objectViewYawHi \ Set A = objectViewYawHi - 10 + T SEC \ SBC #10 \ This sets A to the yaw angle of the viewer's gaze CLC \ towards the object, but relative to the enemy's ADC T \ viewing arc rather than the screen CMP enemyViewingArc \ If A >= enemyViewingArc then the enemy's gaze towards BCS egaz4 \ the target object falls outside the viewing arc, so \ the enemy can't see the target object, so jump to \ egaz4 to return from the subroutine with the C flag \ set to indicate that the target object can't be seen LDA angleLo \ Set vectorYawAngle(Hi Lo) = angle(Hi Lo) STA vectorYawAngleLo \ LDA angleHi \ So vectorYawAngle(Hi Lo) is the yaw angle of the enemy STA vectorYawAngleHi \ gaze towards the object, as taken from the triangle on \ the ground LDA #2 \ Set gazeCheckCounter = 2 so we perform the gaze check STA gazeCheckCounter \ twice in the loop below, once for the gaze from the \ enemy to the target object, and once for the gaze from \ the enemy to the target object's tile LDA objTypeToAnalyse \ Set A to the type of object #Y, i.e. the object being \ looked at by the enemy, which was set by the call to \ GetObjectAngles above BNE egaz2 \ If the enemy is not looking at a robot (an object of \ type 0), then jump to egaz2 to skip the first check \ against the target object and move on to checking the \ target object's tile \ If we get here then the enemy is looking towards a \ robot, so we now check whether the enemy can actually \ see the robot object \ \ The results will end up in bit 6 of targetVisibility \ and treeVisibility, as the first pass will rotate the \ results into bit 7 of the result variables, and the \ second pass will then rotate this first result down \ into bit 6 SEC \ Set bit 7 of enemyCheckingRobot so the call to the ROR enemyCheckingRobot \ FollowGazeVector routine below will know that the \ enemy is looking towards a robot \ \ This tells FollowGazeVector to return a positive \ result for looking at the robot even when the viewer \ is lower than the robot, so even though the enemy \ can't see the tile that the robot is standing on, it \ will still record that the enemy can see the robot \ object (so the robot is partially visible and we can \ use this to fill in the scanner halfway) LDA yDeltaLo \ Set (A xDeltaLo) = yDelta(Hi Lo) STA xDeltaLo \ LDA yDeltaHi \ The call to GetObjectAngles set yDelta(Hi Lo) to the \ difference in altitude between the enemy and the \ object, so we put this into (A xDeltaLo) to pass to \ GetPitchAngleDelta to calculate the pitch angle of the \ gaze from the enemy to the object \ Because the enemy is looking towards a robot, we do \ the following loop twice, using the counter we set in \ gazeCheckCounter \ \ The first time we follow the gaze from the enemy to \ the target object, and the second time we follow the \ gaze from the enemy to the target object's tile .egaz1 JSR GetPitchAngleDelta \ Set angle(Hi Lo) to the pitch angle of the vector \ along the hypotenuse of the vertical pitch angle \ triangle, given a vertical opposite side of length \ (A xDeltaLo) and an adjacent side along the ground of \ length hypotenuse(Hi Lo) \ \ So we now have the pitch angle of the vector from the \ enemy to the object LDA angleLo \ Set vectorPitchAngle(Hi Lo) = angle(Hi Lo) STA vectorPitchAngleLo \ STA T \ So vectorYawAngle(Hi Lo) is the pitch angle of the LDA angleHi \ enemy towards the object, as taken from the vertical STA vectorPitchAngleHi \ triangle with the gaze vector as the hypotenuse \ \ This also sets T to the low byte in vectorPitchAngleLo JSR GetVectorForAngles \ Convert the pitch and yaw angles of the enemy's gaze \ vector towards the object: \ \ vectorPitchAngle(Hi Lo) \ \ vectorYawAngle(Hi Lo) \ \ into a cartesian vector: \ \ [ xVector(Lo Bot) ] \ [ yVector(Lo Bot) ] \ [ zVector(Lo Bot) ] \ \ So this is the gaze vector from the enemy to the \ object we are checking JSR FollowGazeVector \ Follow the gaze vector from the viewing object to \ determine whether the enemy can see a flat tile or \ platform (i.e. boulder or tower) or the target object \ \ This sets the C flag as follows: \ \ * Clear if the viewing object can see a tile along \ the gaze vector \ \ * Set if the viewing object can't see a tile along \ the gaze vector \ \ It also sets bit 7 of targetOnTile depending on \ whether the gaze vector can see a tile containing the \ object whose number is in targetObject: \ \ * Bit 7 clear = gaze vector cannot see the target \ object \ \ * Bit 7 set = gaze vector can see the target object \ \ and if the gaze cannot see the target, then bit 7 of \ gazeCanSeeTree is set depending on whether the gaze \ vector can see a tree: \ \ * Bit 7 clear = gaze vector cannot see a tree \ \ * Bit 7 set = gaze vector can see a tree \ \ If we call this with bit 7 of enemyCheckingRobot set, \ which we do on the first pass when the enemy is \ looking at a robot, then this will return a positive \ response even if the enemy is at a lower altitude than \ the robot and can't see the tile that the robot is on, \ so this lets us record partial visibility of robots \ The following rotations ensure that we record the \ results correctly in the targetVisibility and \ treeVisibility variables: \ \ * If the enemy is looking at a robot then they will \ ensure that bit 6 records the results when looking \ at the robot, and bit 7 records the results when \ looking at the robot's tile \ \ * If the enemy is not looking at a robot then they \ will ensure that bit 7 records the results of \ looking at the target object's tile ROL targetOnTile \ Rotate bit 7 of targetOnTile into bit 7 of ROR targetVisibility \ targetVisibility ROL gazeCanSeeTree \ Rotate bit 7 of gazeCanSeeTree into bit 7 of ROR treeVisibility \ treeVisibility .egaz2 LSR enemyCheckingRobot \ Clear bit 7 of enemyCheckingRobot to pass to the next \ call to FollowGazeVector, so it returns results for \ the tile visibility rather than the object itself (so \ this will be on the second call if we are looking at a \ robot, or the only call if we are not looking at a \ robot) LDA yDeltaLo \ Set (A xDeltaLo) = yDelta(Hi Lo) - &E0 SEC \ = yDelta(Hi Lo) - 224 SBC #&E0 \ STA xDeltaLo \ The object is spawned at a y-coordinate of 224 above LDA yDeltaHi \ the tile, so this sets (A xDeltaLo) to the altitude of SBC #&00 \ the target object's tile rather than the target object \ itself DEC gazeCheckCounter \ Decrement the loop counter in gazeCheckCounter BNE egaz1 \ Loop back to repeat the check, but this time using the \ gaze vector from the enemy to the target object's tile .egaz3 CLC \ Clear the C flag to return from the subroutine to \ indicate that we have performed the gaze checks .egaz4 LDX xStoreEnemyGaze \ Restore the value of X from xStoreEnemyGaze that we \ stored at the start of the routine, so that it's \ preserved LDY targetObject \ Set Y to targetObject so that Y is preserved RTS \ Return from the subroutine