bool CCollision::IsThrough(int x, int y, int xoff, int yoff, vec2 pos0, vec2 pos1) { int pos = GetPureMapIndex(x, y); if(m_pFront && (m_pFront[pos].m_Index == TILE_THROUGH_ALL || m_pFront[pos].m_Index == TILE_THROUGH_CUT)) return true; if(m_pFront && m_pFront[pos].m_Index == TILE_THROUGH_DIR && ( (m_pFront[pos].m_Flags == ROTATION_0 && pos0.y > pos1.y) || (m_pFront[pos].m_Flags == ROTATION_90 && pos0.x < pos1.x) || (m_pFront[pos].m_Flags == ROTATION_180 && pos0.y < pos1.y) || (m_pFront[pos].m_Flags == ROTATION_270 && pos0.x > pos1.x) )) return true; int offpos = GetPureMapIndex(x+xoff, y+yoff); if(m_pTiles[offpos].m_Index == TILE_THROUGH || (m_pFront && m_pFront[offpos].m_Index == TILE_THROUGH)) return true; return false; }
int CCollision::IntersectLineTeleHook(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision, int *pTeleNr) { float Distance = distance(Pos0, Pos1); int End(Distance+1); vec2 Last = Pos0; int ix = 0, iy = 0; // Temporary position for checking collision int dx = 0, dy = 0; // Offset for checking the "through" tile ThroughOffset(Pos0, Pos1, &dx, &dy); for(int i = 0; i <= End; i++) { float a = i/(float)End; vec2 Pos = mix(Pos0, Pos1, a); ix = round_to_int(Pos.x); iy = round_to_int(Pos.y); int Index = GetPureMapIndex(Pos); if (g_Config.m_SvOldTeleportHook) *pTeleNr = IsTeleport(Index); else *pTeleNr = IsTeleportHook(Index); if(*pTeleNr) { if(pOutCollision) *pOutCollision = Pos; if(pOutBeforeCollision) *pOutBeforeCollision = Last; return TILE_TELEINHOOK; } int hit = 0; if(CheckPoint(ix, iy)) { if(!IsThrough(ix, iy, dx, dy, Pos0, Pos1)) hit = GetCollisionAt(ix, iy); } else if(IsHookBlocker(ix, iy, Pos0, Pos1)) { hit = TILE_NOHOOK; } if(hit) { if(pOutCollision) *pOutCollision = Pos; if(pOutBeforeCollision) *pOutBeforeCollision = Last; return hit; } Last = Pos; } if(pOutCollision) *pOutCollision = Pos1; if(pOutBeforeCollision) *pOutBeforeCollision = Pos1; return 0; }
bool CCollision::GetRadTiles(int tilemap, vec2 pos, int *index, int *flags, int team) { static const float sProximityRadius = 14.0f; // FIXME: Perhaps best TILE_SIZE/2? static const float sOffset = 4.0f; const int tmpIndex[] = { GetPureMapIndex(pos), // Current GetPureMapIndex(vec2(pos.x + sProximityRadius + sOffset, pos.y)), // Left GetPureMapIndex(vec2(pos.x - sProximityRadius - sOffset, pos.y)), // Right GetPureMapIndex(vec2(pos.x, pos.y + sProximityRadius + sOffset)), // Top GetPureMapIndex(vec2(pos.x, pos.y - sProximityRadius - sOffset)) // Bottom }; if (tilemap == TILEMAP_SWITCH && m_pSwitchers) { for (int i=0; i<5; i++) { index[i] = m_pSwitchers[m_pDoor[tmpIndex[i]].m_Number].m_Status[team]?m_pDoor[tmpIndex[i]].m_Index:0; flags[i] = m_pSwitchers[m_pDoor[tmpIndex[i]].m_Number].m_Status[team]?m_pDoor[tmpIndex[i]].m_Flags:0; } } else if (tilemap == TILEMAP_GAME && m_pTiles) { for (int i=0; i<5; i++) { index[i] = m_pTiles[tmpIndex[i]].m_Index; flags[i] = m_pTiles[tmpIndex[i]].m_Flags; } } else if (tilemap == TILEMAP_FRONT && m_pFront) { for (int i=0; i<5; i++) { index[i] = m_pFront[tmpIndex[i]].m_Index; flags[i] = m_pFront[tmpIndex[i]].m_Flags; } } else return false; return true; }
int CCollision::IntersectLineTeleWeapon(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision, int *pTeleNr) { float Distance = distance(Pos0, Pos1); int End(Distance+1); vec2 Last = Pos0; int ix = 0, iy = 0; // Temporary position for checking collision for(int i = 0; i <= End; i++) { float a = i/(float)End; vec2 Pos = mix(Pos0, Pos1, a); ix = round_to_int(Pos.x); iy = round_to_int(Pos.y); int Index = GetPureMapIndex(Pos); if (g_Config.m_SvOldTeleportWeapons) *pTeleNr = IsTeleport(Index); else *pTeleNr = IsTeleportWeapon(Index); if(*pTeleNr) { if(pOutCollision) *pOutCollision = Pos; if(pOutBeforeCollision) *pOutBeforeCollision = Last; return TILE_TELEINWEAPON; } if(CheckPoint(ix, iy)) { if(pOutCollision) *pOutCollision = Pos; if(pOutBeforeCollision) *pOutBeforeCollision = Last; return GetCollisionAt(ix, iy); } Last = Pos; } if(pOutCollision) *pOutCollision = Pos1; if(pOutBeforeCollision) *pOutBeforeCollision = Pos1; return 0; }
bool CCollision::IsHookBlocker(int x, int y, vec2 pos0, vec2 pos1) { int pos = GetPureMapIndex(x, y); if(m_pTiles[pos].m_Index == TILE_THROUGH_ALL || (m_pFront && m_pFront[pos].m_Index == TILE_THROUGH_ALL)) return true; if(m_pTiles[pos].m_Index == TILE_THROUGH_DIR && ( (m_pTiles[pos].m_Flags == ROTATION_0 && pos0.y < pos1.y) || (m_pTiles[pos].m_Flags == ROTATION_90 && pos0.x > pos1.x) || (m_pTiles[pos].m_Flags == ROTATION_180 && pos0.y > pos1.y) || (m_pTiles[pos].m_Flags == ROTATION_270 && pos0.x < pos1.x) )) return true; if(m_pFront && m_pFront[pos].m_Index == TILE_THROUGH_DIR && ( (m_pFront[pos].m_Flags == ROTATION_0 && pos0.y < pos1.y) || (m_pFront[pos].m_Flags == ROTATION_90 && pos0.x > pos1.x) || (m_pFront[pos].m_Flags == ROTATION_180 && pos0.y > pos1.y) || (m_pFront[pos].m_Flags == ROTATION_270 && pos0.x < pos1.x) )) return true; return false; }