/** * @file portal.cpp * * Implementation of functionality for handling town portals. */ #include "portal.h" #include "lighting.h" #include "misdat.h" #include "missiles.h" #include "multi.h" #include "player.h" namespace devilution { /** In-game state of portals. */ PortalStruct Portals[MAXPORTAL]; /** Current portal number (a portal array index). */ int portalindex; /** X-coordinate of each players portal in town. */ int WarpDropX[MAXPORTAL] = { 57, 59, 61, 63 }; /** Y-coordinate of each players portal in town. */ int WarpDropY[MAXPORTAL] = { 40, 40, 40, 40 }; void InitPortals() { for (int i = 0; i < MAXPORTAL; i++) { if (delta_portal_inited(i)) Portals[i].open = false; } } void SetPortalStats(int i, bool o, int x, int y, int lvl, dungeon_type lvltype) { Portals[i].open = o; Portals[i].position = { x, y }; Portals[i].level = lvl; Portals[i].ltype = lvltype; Portals[i].setlvl = false; } void AddWarpMissile(int i, int x, int y) { int mi; MissileData[MIS_TOWN].mlSFX = SFX_NONE; dMissile[x][y] = 0; mi = AddMissile({ 0, 0 }, { x, y }, 0, MIS_TOWN, TARGET_MONSTERS, i, 0, 0); if (mi != -1) { SetMissDir(mi, 1); if (currlevel != 0) Missiles[mi]._mlid = AddLight(Missiles[mi].position.tile, 15); MissileData[MIS_TOWN].mlSFX = LS_SENTINEL; } } void SyncPortals() { for (int i = 0; i < MAXPORTAL; i++) { if (!Portals[i].open) continue; if (currlevel == 0) AddWarpMissile(i, WarpDropX[i], WarpDropY[i]); else { int lvl = currlevel; if (setlevel) lvl = setlvlnum; if (Portals[i].level == lvl && Portals[i].setlvl == setlevel) AddWarpMissile(i, Portals[i].position.x, Portals[i].position.y); } } } void AddInTownPortal(int i) { AddWarpMissile(i, WarpDropX[i], WarpDropY[i]); } void ActivatePortal(int i, int x, int y, int lvl, dungeon_type lvltype, bool sp) { Portals[i].open = true; if (lvl != 0) { Portals[i].position = { x, y }; Portals[i].level = lvl; Portals[i].ltype = lvltype; Portals[i].setlvl = sp; } } void DeactivatePortal(int i) { Portals[i].open = false; } bool PortalOnLevel(int i) { if (Portals[i].level == currlevel) return true; return currlevel == 0; } void RemovePortalMissile(int id) { for (int i = 0; i < ActiveMissileCount; i++) { int mi = ActiveMissiles[i]; if (Missiles[mi]._mitype == MIS_TOWN && Missiles[mi]._misource == id) { dFlags[Missiles[mi].position.tile.x][Missiles[mi].position.tile.y] &= ~BFLAG_MISSILE; dMissile[Missiles[mi].position.tile.x][Missiles[mi].position.tile.y] = 0; if (Portals[id].level != 0) AddUnLight(Missiles[mi]._mlid); DeleteMissile(mi, i); } } } void SetCurrentPortal(int p) { portalindex = p; } void GetPortalLevel() { if (currlevel != 0) { setlevel = false; currlevel = 0; Players[MyPlayerId].plrlevel = 0; leveltype = DTYPE_TOWN; return; } if (Portals[portalindex].setlvl) { setlevel = true; setlvlnum = (_setlevels)Portals[portalindex].level; currlevel = Portals[portalindex].level; Players[MyPlayerId].plrlevel = setlvlnum; leveltype = Portals[portalindex].ltype; } else { setlevel = false; currlevel = Portals[portalindex].level; Players[MyPlayerId].plrlevel = currlevel; leveltype = Portals[portalindex].ltype; } if (portalindex == MyPlayerId) { NetSendCmd(true, CMD_DEACTIVATEPORTAL); DeactivatePortal(portalindex); } } void GetPortalLvlPos() { if (currlevel == 0) { ViewX = WarpDropX[portalindex] + 1; ViewY = WarpDropY[portalindex] + 1; } else { ViewX = Portals[portalindex].position.x; ViewY = Portals[portalindex].position.y; if (portalindex != MyPlayerId) { ViewX++; ViewY++; } } } bool PosOkPortal(int lvl, int x, int y) { for (auto &portal : Portals) { if (portal.open && portal.level == lvl && ((portal.position.x == x && portal.position.y == y) || (portal.position.x == x - 1 && portal.position.y == y - 1))) return true; } return false; } } // namespace devilution