@@ -1077,6 +1077,94 @@ void SceneMan::RestoreUnseenBox(const int posX, const int posY, const int width,
1077
1077
}
1078
1078
}
1079
1079
1080
+ bool SceneMan::CastTerrainPenetrationRay (const Vector& start, const Vector& ray, Vector& endPos, int strengthLimit, int skip) {
1081
+ int hitCount = 0 , error, dom, sub, domSteps, skipped = skip;
1082
+ int intPos[2 ], delta[2 ], delta2[2 ], increment[2 ];
1083
+ bool stopped = false ;
1084
+ unsigned char materialID;
1085
+ Material const * foundMaterial;
1086
+ int totalStrength = 0 ;
1087
+ // Save the projected end of the ray pos
1088
+ endPos = start + ray;
1089
+
1090
+ intPos[X] = std::floor (start.m_X );
1091
+ intPos[Y] = std::floor (start.m_Y );
1092
+ delta[X] = std::floor (start.m_X + ray.m_X ) - intPos[X];
1093
+ delta[Y] = std::floor (start.m_Y + ray.m_Y ) - intPos[Y];
1094
+
1095
+ if (delta[X] == 0 && delta[Y] == 0 )
1096
+ return false ;
1097
+
1098
+ // ///////////////////////////////////////////////////
1099
+ // Bresenham's line drawing algorithm preparation
1100
+
1101
+ if (delta[X] < 0 ) {
1102
+ increment[X] = -1 ;
1103
+ delta[X] = -delta[X];
1104
+ } else
1105
+ increment[X] = 1 ;
1106
+
1107
+ if (delta[Y] < 0 ) {
1108
+ increment[Y] = -1 ;
1109
+ delta[Y] = -delta[Y];
1110
+ } else
1111
+ increment[Y] = 1 ;
1112
+
1113
+ // Scale by 2, for better accuracy of the error at the first pixel
1114
+ delta2[X] = delta[X] << 1 ;
1115
+ delta2[Y] = delta[Y] << 1 ;
1116
+
1117
+ // If X is dominant, Y is submissive, and vice versa.
1118
+ if (delta[X] > delta[Y]) {
1119
+ dom = X;
1120
+ sub = Y;
1121
+ } else {
1122
+ dom = Y;
1123
+ sub = X;
1124
+ }
1125
+
1126
+ error = delta2[sub] - delta[dom];
1127
+
1128
+ // ///////////////////////////////////////////////////
1129
+ // Bresenham's line drawing algorithm execution
1130
+
1131
+ for (domSteps = 0 ; domSteps < delta[dom]; ++domSteps) {
1132
+ intPos[dom] += increment[dom];
1133
+ if (error >= 0 ) {
1134
+ intPos[sub] += increment[sub];
1135
+ error -= delta2[dom];
1136
+ }
1137
+ error += delta2[sub];
1138
+
1139
+ // Only check pixel if we're not due to skip any, or if this is the last pixel
1140
+ if (++skipped > skip || domSteps + 1 == delta[dom]) {
1141
+ // Scene wrapping
1142
+ g_SceneMan.WrapPosition (intPos[X], intPos[Y]);
1143
+
1144
+ // Check the strength of the terrain to see if we can penetrate further
1145
+ materialID = GetTerrMatter (intPos[X], intPos[Y]);
1146
+ // Get the material object
1147
+ foundMaterial = GetMaterialFromID (materialID);
1148
+ // Add the encountered material's strength to the tally
1149
+ totalStrength += foundMaterial->GetIntegrity ();
1150
+ // See if we have hit the limits of our ray's strength
1151
+ if (totalStrength >= strengthLimit) {
1152
+ // Save the position of the end of the ray where blocked
1153
+ endPos.SetXY (intPos[X], intPos[Y]);
1154
+ stopped = true ;
1155
+ break ;
1156
+ }
1157
+ // Reset skip counter
1158
+ skipped = 0 ;
1159
+ if (m_pDebugLayer && m_DrawRayCastVisualizations) {
1160
+ m_pDebugLayer->SetPixel (intPos[X], intPos[Y], 13 );
1161
+ }
1162
+ }
1163
+ }
1164
+
1165
+ return stopped;
1166
+ }
1167
+
1080
1168
// TODO Every raycast should use some shared line drawing method (or maybe something more efficient if it exists, that needs looking into) instead of having a ton of duplicated code.
1081
1169
bool SceneMan::CastUnseenRay (int team, const Vector& start, const Vector& ray, Vector& endPos, int strengthLimit, int skip, bool reveal) {
1082
1170
if (!m_pCurrentScene->GetUnseenLayer (team))
0 commit comments