We should follow the HandBook
[tuxanci.git] / src / modules / modTeleport.c
blobb7ca273ec78becbb6f2d62c9425400d61b253ffd
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <assert.h>
6 #include "main.h"
7 #include "modules.h"
8 #include "tux.h"
9 #include "shot.h"
10 #include "list.h"
11 #include "gun.h"
12 #include "space.h"
14 #ifndef PUBLIC_SERVER
15 #include "interface.h"
16 #include "image.h"
17 #else
18 #include "publicServer.h"
19 #endif
21 typedef struct teleport_struct {
22 int id;
24 /* position of the teleport */
25 int x;
26 int y;
28 /* size of the teleport */
29 int w;
30 int h;
32 /* layer in the arena where the teleport lies */
33 int layer;
35 #ifndef PUBLIC_SERVER
36 /* its image */
37 image_t *img;
38 #endif
39 } teleport_t;
41 static export_fce_t *export_fce;
43 static space_t *spaceTeleport;
44 static list_t *listTeleport;
46 static void (*fce_move_tux) (tux_t *tux, int x, int y, int w, int h);
47 static void (*fce_move_shot) (shot_t *shot, int position, int src_x,
48 int src_y, int dist_x, int dist_y, int dist_w,
49 int dist_h);
51 #ifndef PUBLIC_SERVER
52 static teleport_t *newTeleport(int x, int y, int w, int h, int layer, image_t *img)
53 #else
54 static teleport_t *newTeleport(int x, int y, int w, int h, int layer)
55 #endif
57 static int last_id = 0;
59 teleport_t *new;
61 #ifndef PUBLIC_SERVER
62 assert(img != NULL);
63 #endif
65 new = malloc(sizeof(teleport_t));
66 assert(new != NULL);
68 new->id = ++last_id;
69 new->x = x;
70 new->y = y;
71 new->w = w;
72 new->h = h;
73 new->layer = layer;
74 #ifndef PUBLIC_SERVER
75 new->img = img;
76 #endif
78 return new;
81 static void setStatusTeleport(void *p, int x, int y, int w, int h)
83 teleport_t *teleport;
85 teleport = p;
87 teleport->x = x;
88 teleport->y = y;
89 teleport->w = w;
90 teleport->h = h;
93 static void getStatusTeleport(void *p, int *id, int *x, int *y, int *w, int *h)
95 teleport_t *teleport;
96 teleport = p;
98 *id = teleport->id;
99 *x = teleport->x;
100 *y = teleport->y;
101 *w = teleport->w;
102 *h = teleport->h;
105 #ifndef PUBLIC_SERVER
106 static void drawTeleport(teleport_t *p)
108 assert(p != NULL);
110 export_fce->fce_addLayer(p->img, p->x, p->y, 0, 0, p->img->w, p->img->h, p->layer);
112 #endif
114 static void destroyTeleport(teleport_t *p)
116 assert(p != NULL);
117 free(p);
120 static void cmd_teleport(char *line)
122 char str_x[STR_NUM_SIZE];
123 char str_y[STR_NUM_SIZE];
124 char str_w[STR_NUM_SIZE];
125 char str_h[STR_NUM_SIZE];
126 char str_layer[STR_NUM_SIZE];
127 char str_image[STR_SIZE];
128 teleport_t *new;
130 if (export_fce->fce_getValue(line, "x", str_x, STR_NUM_SIZE) != 0)
131 return;
132 if (export_fce->fce_getValue(line, "y", str_y, STR_NUM_SIZE) != 0)
133 return;
134 if (export_fce->fce_getValue(line, "w", str_w, STR_NUM_SIZE) != 0)
135 return;
136 if (export_fce->fce_getValue(line, "h", str_h, STR_NUM_SIZE) != 0)
137 return;
138 if (export_fce->fce_getValue(line, "layer", str_layer, STR_NUM_SIZE) != 0)
139 return;
140 if (export_fce->fce_getValue(line, "image", str_image, STR_SIZE) != 0)
141 return;
143 #ifndef PUBLIC_SERVER
144 new = newTeleport(atoi(str_x), atoi(str_y),
145 atoi(str_w), atoi(str_h),
146 atoi(str_layer),
147 export_fce->fce_image_get(IMAGE_GROUP_USER, str_image));
148 #else
149 new = newTeleport(atoi(str_x), atoi(str_y),
150 atoi(str_w), atoi(str_h),
151 atoi(str_layer));
152 #endif
154 if (spaceTeleport == NULL) {
155 spaceTeleport = space_new(export_fce->fce_arena_get_current()->w,
156 export_fce->fce_arena_get_current()->h,
157 320, 240,
158 getStatusTeleport, setStatusTeleport);
161 space_add(spaceTeleport, new);
164 static teleport_t *getRandomTeleportBut(space_t *space, teleport_t *teleport)
166 int my_index;
168 do {
169 my_index = random() % space_get_count(space);
170 } while (space_get_item(space, my_index) == teleport);
172 return (teleport_t *) space_get_item(space, my_index);
175 static int getRandomPosition()
177 switch (random() % 4) {
178 case 0:
179 return TUX_UP;
181 case 1:
182 return TUX_LEFT;
184 case 2:
185 return TUX_RIGHT;
187 case 3:
188 return TUX_DOWN;
191 fatal("Generated a random number which is not in range 0 to 3");
193 return -1; /* no warnings */
196 static void teleportTux(tux_t *tux, teleport_t *teleport)
198 teleport_t *distTeleport;
200 if (tux->bonus == BONUS_GHOST ||
201 export_fce->fce_net_multiplayer_get_game_type() == NET_GAME_TYPE_CLIENT) {
202 return;
205 distTeleport = getRandomTeleportBut(spaceTeleport, teleport);
207 fce_move_tux(tux, distTeleport->x, distTeleport->y, distTeleport->w, distTeleport->h);
210 static void moveShotFromTeleport(shot_t *shot, teleport_t *teleport, space_t *space)
212 teleport_t *distTeleport;
214 distTeleport = getRandomTeleportBut(space, teleport);
216 fce_move_shot(shot, getRandomPosition(), teleport->x, teleport->y,
217 distTeleport->x, distTeleport->y, distTeleport->w,
218 distTeleport->h);
221 static int init(export_fce_t *p)
223 export_fce = p;
225 listTeleport = list_new();
227 if (export_fce->fce_module_load_dep("libmodMove") != 0) {
228 return -1;
231 if ((fce_move_tux = export_fce->fce_share_function_get("move_tux")) == NULL) {
232 return -1;
235 if ((fce_move_shot = export_fce->fce_share_function_get("move_shot")) == NULL) {
236 return -1;
239 return 0;
242 #ifndef PUBLIC_SERVER
243 static void action_drawteleport(space_t *space, teleport_t *teleport, void *p)
245 UNUSED(space);
246 UNUSED(p);
248 drawTeleport(teleport);
251 static int draw(int x, int y, int w, int h)
253 if (spaceTeleport == NULL) {
254 return 0;
257 space_action_from_location(spaceTeleport, action_drawteleport, NULL, x, y, w, h);
259 return 0;
261 #endif
263 static void action_eventteleportshot(space_t *space, teleport_t *teleport, shot_t *shot)
265 arena_t *arena;
266 tux_t *author;
268 UNUSED(space);
270 arena = export_fce->fce_arena_get_current();
272 author = space_get_object_id(arena->spaceTux, shot->author_id);
274 if (author != NULL && author->bonus == BONUS_GHOST && author->bonus_time > 0) {
275 return;
278 moveShotFromTeleport(shot, teleport, spaceTeleport);
281 static void action_eventshot(space_t *space, shot_t *shot, space_t *p_spaceTeleport)
283 UNUSED(space);
285 space_action_from_location(p_spaceTeleport, action_eventteleportshot,
286 shot, shot->x, shot->y, shot->w, shot->h);
289 static void action_eventteleporttux(space_t *space, teleport_t *teleport, tux_t *tux)
291 UNUSED(space);
293 teleportTux(tux, teleport);
296 static void action_eventtux(space_t *space, tux_t *tux, space_t *p_spaceTeleport)
298 int x, y, w, h;
300 UNUSED(space);
302 export_fce->fce_tux_get_proportion(tux, &x, &y, &w, &h);
304 space_action_from_location(p_spaceTeleport, action_eventteleporttux, tux, x, y, w, h);
307 static int event()
309 if (spaceTeleport == NULL) {
310 return 0;
313 if (export_fce->fce_net_multiplayer_get_game_type() == NET_GAME_TYPE_CLIENT) {
314 return 0;
317 space_action(export_fce->fce_arena_get_current()->spaceShot, action_eventshot, spaceTeleport);
318 space_action(export_fce->fce_arena_get_current()->spaceTux, action_eventtux, spaceTeleport);
320 return 0;
323 static int isConflict(int x, int y, int w, int h)
325 UNUSED(x);
326 UNUSED(y);
327 UNUSED(w);
328 UNUSED(h);
330 if (spaceTeleport == NULL) {
331 return 0;
334 return 0;
337 static void cmdArena(char *line)
339 if (strncmp(line, "teleport", 8) == 0) {
340 cmd_teleport(line);
344 static void recvMsg(char *msg)
346 UNUSED(msg);
349 static int destroy()
351 space_destroy_with_item(spaceTeleport, destroyTeleport);
352 spaceTeleport = NULL;
354 list_destroy(listTeleport);
355 listTeleport = NULL;
357 return 0;
360 mod_sym_t modteleport_sym = { &init,
361 #ifndef PUBLIC_SERVER
362 &draw,
363 #else
365 #endif
366 &event,
367 &isConflict,
368 &cmdArena,
369 &recvMsg,
370 &destroy };