1 /*
2 Copyright (C) 2009-2021 Parallel Realities
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18 */
19 
20 #include "../headers.h"
21 
22 #include "../audio/audio.h"
23 #include "../collisions.h"
24 #include "../entity.h"
25 #include "../game.h"
26 #include "../geometry.h"
27 #include "../graphics/animation.h"
28 #include "../graphics/decoration.h"
29 #include "../hud.h"
30 #include "../system/error.h"
31 #include "../system/properties.h"
32 #include "../system/random.h"
33 
34 extern Entity *self;
35 extern Game game;
36 
37 static void entityWait(void);
38 static int draw(void);
39 static void activate(int);
40 static void touch(Entity *);
41 static void nextLevelPause(void);
42 
addTeleporter(char * name,int x,int y)43 Entity *addTeleporter(char *name, int x, int y)
44 {
45 	Entity *e = getFreeEntity();
46 
47 	if (e == NULL)
48 	{
49 		showErrorAndExit("No free slots to add a Teleporter");
50 	}
51 
52 	loadProperties("common/teleporter", e);
53 
54 	STRNCPY(e->name, name, sizeof(e->name));
55 
56 	e->touch = &touch;
57 
58 	e->action = &entityWait;
59 
60 	e->draw = &draw;
61 
62 	e->activate = &activate;
63 
64 	e->x = x;
65 	e->y = y;
66 
67 	e->flags |= OBSTACLE;
68 
69 	setEntityAnimation(e, "STAND");
70 
71 	return e;
72 }
73 
entityWait()74 static void entityWait()
75 {
76 	self->face = RIGHT;
77 
78 	if (self->active == FALSE)
79 	{
80 		setEntityAnimation(self, "STAND");
81 	}
82 
83 	else
84 	{
85 		setEntityAnimation(self, "WALK");
86 	}
87 
88 	checkToMap(self);
89 }
90 
draw()91 static int draw()
92 {
93 	Entity *e;
94 
95 	if (drawLoopingAnimationToMap() == TRUE && self->active == TRUE)
96 	{
97 		if (prand() % 3 == 0)
98 		{
99 			e = addBasicDecoration(self->x + self->w / 2, self->y, "decoration/particle");
100 
101 			if (e != NULL)
102 			{
103 				e->x += (prand() % 16) * (prand() % 2 == 0 ? -1 : 1);
104 
105 				e->y -= e->h;
106 
107 				e->thinkTime = 30 + prand() % 60;
108 
109 				e->dirY = -5 - prand() % 15;
110 
111 				e->dirY /= 10;
112 
113 				e->alpha = 128;
114 
115 				setEntityAnimationByID(e, prand() % 5);
116 			}
117 		}
118 	}
119 
120 	return TRUE;
121 }
122 
touch(Entity * other)123 static void touch(Entity *other)
124 {
125 	pushEntity(other);
126 
127 	if (other->standingOn == self && !(other->flags & TELEPORTING))
128 	{
129 		if (self->active == TRUE)
130 		{
131 			self->target = other;
132 
133 			activate(1);
134 		}
135 
136 		else if (other->type == PLAYER)
137 		{
138 			setInfoBoxMessage(0, 255, 255, 255, _("This teleporter is not active"));
139 		}
140 	}
141 }
142 
activate(int val)143 static void activate(int val)
144 {
145 	if (strlen(self->objectiveName) == 0)
146 	{
147 		/* Internal teleport */
148 
149 		self->target->targetX = self->endX;
150 		self->target->targetY = self->endY;
151 
152 		calculatePath(self->target->x, self->target->y, self->target->targetX, self->target->targetY, &self->target->dirX, &self->target->dirY);
153 
154 		self->target->flags |= (NO_DRAW|HELPLESS|TELEPORTING);
155 
156 		playSoundToMap("sound/common/teleport", (self->target->type == PLAYER ? EDGAR_CHANNEL : -1), self->target->x, self->target->y, 0);
157 	}
158 
159 	else if (self->target->type == PLAYER)
160 	{
161 		/* External teleport */
162 
163 		self->target->flags |= (NO_DRAW|HELPLESS|TELEPORTING);
164 
165 		self->thinkTime = 90;
166 
167 		self->target->dirX = 0;
168 		self->target->dirY = 0;
169 
170 		self->action = &nextLevelPause;
171 
172 		addParticleExplosion(self->target->x + self->target->w / 2, self->target->y + self->target->h / 2);
173 
174 		playSoundToMap("sound/common/teleport", (self->target->type == PLAYER ? EDGAR_CHANNEL : -1), self->target->x, self->target->y, 0);
175 	}
176 
177 	self->target->standingOn = NULL;
178 
179 	self->target = NULL;
180 }
181 
nextLevelPause()182 static void nextLevelPause()
183 {
184 	char mapName[MAX_VALUE_LENGTH];
185 
186 	self->thinkTime--;
187 
188 	if (self->thinkTime <= 0)
189 	{
190 		SNPRINTF(mapName, sizeof(mapName), "%s %s", self->objectiveName, self->name);
191 
192 		setNextLevelFromScript(mapName);
193 
194 		self->action = &entityWait;
195 	}
196 
197 	checkToMap(self);
198 }
199