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