1 /**
2  * @file portal.cpp
3  *
4  * Implementation of functionality for handling town portals.
5  */
6 #include "all.h"
7 
8 DEVILUTION_BEGIN_NAMESPACE
9 
10 /** In-game state of portals. */
11 PortalStruct portal[MAXPORTAL];
12 /** Current portal number (a portal array index). */
13 int portalindex;
14 
15 /** X-coordinate of each players portal in town. */
16 int WarpDropX[MAXPORTAL] = { 57, 59, 61, 63 };
17 /** Y-coordinate of each players portal in town. */
18 int WarpDropY[MAXPORTAL] = { 40, 40, 40, 40 };
19 
InitPortals()20 void InitPortals()
21 {
22 	int i;
23 
24 	for (i = 0; i < MAXPORTAL; i++) {
25 		if (delta_portal_inited(i))
26 			portal[i].open = FALSE;
27 	}
28 }
29 
SetPortalStats(int i,BOOL o,int x,int y,int lvl,dungeon_type lvltype)30 void SetPortalStats(int i, BOOL o, int x, int y, int lvl, dungeon_type lvltype)
31 {
32 	portal[i].open = o;
33 	portal[i].x = x;
34 	portal[i].y = y;
35 	portal[i].level = lvl;
36 	portal[i].ltype = lvltype;
37 	portal[i].setlvl = FALSE;
38 }
39 
AddWarpMissile(int i,int x,int y)40 void AddWarpMissile(int i, int x, int y)
41 {
42 	int mi;
43 
44 	missiledata[MIS_TOWN].mlSFX = -1;
45 	dMissile[x][y] = 0;
46 	mi = AddMissile(0, 0, x, y, 0, MIS_TOWN, TARGET_MONSTERS, i, 0, 0);
47 
48 	if (mi != -1) {
49 		SetMissDir(mi, 1);
50 
51 		if (currlevel != 0)
52 			missile[mi]._mlid = AddLight(missile[mi]._mix, missile[mi]._miy, 15);
53 
54 		missiledata[MIS_TOWN].mlSFX = LS_SENTINEL;
55 	}
56 }
57 
SyncPortals()58 void SyncPortals()
59 {
60 	int i;
61 
62 	for (i = 0; i < MAXPORTAL; i++) {
63 		if (!portal[i].open)
64 			continue;
65 		if (currlevel == 0)
66 			AddWarpMissile(i, WarpDropX[i], WarpDropY[i]);
67 		else {
68 			int lvl = currlevel;
69 			if (setlevel)
70 				lvl = setlvlnum;
71 			if (portal[i].level == lvl && portal[i].setlvl == setlevel)
72 				AddWarpMissile(i, portal[i].x, portal[i].y);
73 		}
74 	}
75 }
76 
AddInTownPortal(int i)77 void AddInTownPortal(int i)
78 {
79 	AddWarpMissile(i, WarpDropX[i], WarpDropY[i]);
80 }
81 
ActivatePortal(int i,int x,int y,int lvl,dungeon_type lvltype,BOOL sp)82 void ActivatePortal(int i, int x, int y, int lvl, dungeon_type lvltype, BOOL sp)
83 {
84 	portal[i].open = TRUE;
85 
86 	if (lvl != 0) {
87 		portal[i].x = x;
88 		portal[i].y = y;
89 		portal[i].level = lvl;
90 		portal[i].ltype = lvltype;
91 		portal[i].setlvl = sp;
92 	}
93 }
94 
DeactivatePortal(int i)95 void DeactivatePortal(int i)
96 {
97 	portal[i].open = FALSE;
98 }
99 
PortalOnLevel(int i)100 BOOL PortalOnLevel(int i)
101 {
102 	if (portal[i].level == currlevel)
103 		return TRUE;
104 	else
105 		return currlevel == 0;
106 }
107 
RemovePortalMissile(int id)108 void RemovePortalMissile(int id)
109 {
110 	int i;
111 	int mi;
112 
113 	for (i = 0; i < nummissiles; i++) {
114 		mi = missileactive[i];
115 		if (missile[mi]._mitype == MIS_TOWN && missile[mi]._misource == id) {
116 			dFlags[missile[mi]._mix][missile[mi]._miy] &= ~BFLAG_MISSILE;
117 			dMissile[missile[mi]._mix][missile[mi]._miy] = 0;
118 
119 			if (portal[id].level != 0)
120 				AddUnLight(missile[mi]._mlid);
121 
122 			DeleteMissile(mi, i);
123 		}
124 	}
125 }
126 
SetCurrentPortal(int p)127 void SetCurrentPortal(int p)
128 {
129 	portalindex = p;
130 }
131 
GetPortalLevel()132 void GetPortalLevel()
133 {
134 	if (currlevel != 0) {
135 		setlevel = FALSE;
136 		currlevel = 0;
137 		plr[myplr].plrlevel = 0;
138 		leveltype = DTYPE_TOWN;
139 	} else {
140 		if (portal[portalindex].setlvl) {
141 			setlevel = TRUE;
142 			setlvlnum = portal[portalindex].level;
143 			currlevel = portal[portalindex].level;
144 			plr[myplr].plrlevel = setlvlnum;
145 			leveltype = portal[portalindex].ltype;
146 		} else {
147 			setlevel = FALSE;
148 			currlevel = portal[portalindex].level;
149 			plr[myplr].plrlevel = currlevel;
150 			leveltype = portal[portalindex].ltype;
151 		}
152 		if (portalindex == myplr) {
153 			NetSendCmd(TRUE, CMD_DEACTIVATEPORTAL);
154 			DeactivatePortal(portalindex);
155 		}
156 	}
157 }
158 
GetPortalLvlPos()159 void GetPortalLvlPos()
160 {
161 	if (currlevel == 0) {
162 		ViewX = WarpDropX[portalindex] + 1;
163 		ViewY = WarpDropY[portalindex] + 1;
164 	} else {
165 		ViewX = portal[portalindex].x;
166 		ViewY = portal[portalindex].y;
167 
168 		if (portalindex != myplr) {
169 			ViewX++;
170 			ViewY++;
171 		}
172 	}
173 }
174 
PosOkPortal(int lvl,int x,int y)175 BOOL PosOkPortal(int lvl, int x, int y)
176 {
177 	int i;
178 
179 	for (i = 0; i < MAXPORTAL; i++) {
180 		if (portal[i].open && portal[i].level == lvl && ((portal[i].x == x && portal[i].y == y) || (portal[i].x == x - 1 && portal[i].y == y - 1)))
181 			return TRUE;
182 	}
183 	return FALSE;
184 }
185 
186 DEVILUTION_END_NAMESPACE
187