1 /************************************************************************
2 * This file is part of Wizznic. *
3 * Copyright 2009-2015 Jimmy Christensen <dusted@dusted.dk> *
4 * Wizznic is free software: you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation, either version 3 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * Wizznic 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. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with Wizznic. If not, see <http://www.gnu.org/licenses/>. *
16 ************************************************************************/
17
18 #include "defs.h"
19 #include "sound.h"
20 #include "switch.h"
21 #include "board.h"
22 #include "particles.h"
23 #include "draw.h"
24
25 static void switchReact( playField* pf, int x, int y ); //Should be used only private
26
27
switchSetTargets(playField * pf)28 int switchSetTargets( playField* pf )
29 {
30 //Figure out switch targets
31 listItem* it = &pf->levelInfo->switchList->begin;
32 while( LISTFWD(pf->levelInfo->switchList,it) )
33 {
34 switch_t* sw = (switch_t*)it->data;
35
36 //Sanity check
37 if( !isSwitch( pf->board[sw->sx][sw->sy] ) )
38 {
39 printf("Switch error: List tells there is a switch at %i,%i but that is not the case.\n", sw->sx, sw->sy);
40 free(sw);
41 listRemoveItem(pf->levelInfo->switchList, it, LIST_PREV );
42 continue;
43 }
44
45 //Check that the target is a supported type
46 if( !switchIsValidTarget( pf, sw->dx, sw->dy ) )
47 {
48 printf("Switch error: Switch at %i,%i points at %i,%i but that's not a valid target brick.\n", sw->sx, sw->sy, sw->dx, sw->dy);
49 free(sw);
50 listRemoveItem(pf->levelInfo->switchList, it, LIST_PREV );
51 continue;
52 }
53
54 switchAttachTarget( pf, sw );
55 //We set the switch itself to have alive = -1 which causes it to be updated.
56 pf->board[sw->sx][sw->sy]->isActive = -1;
57
58 }
59
60 return(1);
61 }
62
switchFindTele(playField * pf,int x,int y)63 int switchFindTele( playField* pf, int x, int y )
64 {
65 //When found, we set target = reservedbrick then use sx/dx hack for teleport destination.
66 listItem* it = &pf->levelInfo->teleList->begin;
67 telePort_t* tp;
68
69 while( LISTFWD(pf->levelInfo->teleList, it) )
70 {
71 tp = (telePort_t*)it->data;
72 if( tp->sx == x && tp->sy == y )
73 {
74 return(1);
75 }
76 }
77
78 return(0);
79 }
80
switchIsValidTarget(playField * pf,int x,int y)81 int switchIsValidTarget( playField* pf, int x, int y )
82 {
83
84 if( isWall( pf, x, y ) || isMover(pf->board[x][y]) || switchFindTele(pf, x, y) || ( pf->board[x][y] && (pf->board[x][y]->type==EVILBRICK || pf->board[x][y]->type==COPYBRICK || pf->board[x][y]->type==REMBRICK||pf->board[x][y]->type==SWAPBRICK) ) )
85 {
86 return(1);
87 }
88
89 return(0);
90 }
91
switchAttachTarget(playField * pf,switch_t * sw)92 void switchAttachTarget( playField* pf, switch_t* sw )
93 {
94 //If it's a walltype or mover.
95 if( isWall( pf, sw->dx, sw->dy ) || isMover(pf->board[sw->dx][sw->dy]) || (pf->board[sw->dx][sw->dy] &&(pf->board[sw->dx][sw->dy]->type==EVILBRICK||pf->board[sw->dx][sw->dy]->type==COPYBRICK||pf->board[sw->dx][sw->dy]->type==REMBRICK||pf->board[sw->dx][sw->dy]->type==SWAPBRICK) ) )
96 {
97 pf->board[sw->sx][sw->sy]->target = pf->board[sw->dx][sw->dy];
98 }
99
100 //If it's a teleport
101 if( switchFindTele( pf, sw->dx, sw->dy ) )
102 {
103 //So, the teleport knows that if the teleport has a target brick thats a blocker, it should look at switches, riight...
104 pf->board[sw->sx][sw->sy]->target = pf->blocker;
105 }
106
107 }
108
109 //Tell if a switch is disabled and pointing to x,y
switchAmIEnabled(playField * pf,int x,int y)110 int switchAmIEnabled(playField* pf, int x, int y)
111 {
112 listItem* it=&pf->levelInfo->switchList->begin;
113 switch_t* sw;
114 //Do any switch have this
115 while( LISTFWD(pf->levelInfo->switchList,it) )
116 {
117 sw = (switch_t*)it->data;
118 if( sw->dx==x && sw->dy==y )
119 {
120 return( pf->board[sw->sx][sw->sy]->isActive );
121 }
122 }
123
124 //If no switch points to this brick, it's active.
125 return(1);
126 }
127
switchReact(playField * pf,int x,int y)128 void switchReact( playField* pf, int x, int y )
129 {
130 int newState;
131
132 if( y>0 && pf->board[x][y-1] && ( isBrick(pf->board[x][y-1])||isMover(pf->board[x][y-1])||pf->board[x][y-1]==pf->blockerDst ) )
133 {
134 newState = (pf->board[x][y]->type==SWOFF)?0:1;
135 } else {
136 newState = (pf->board[x][y]->type==SWOFF)?1:0;
137 }
138
139 if( pf->board[x][y]->isActive != newState )
140 {
141 pf->board[x][y]->isActive=newState;
142
143 switchAffectTarget(pf, x, y, newState );
144 if(newState && pf->board[x][y]->type==SWON)
145 {
146 sndPlay( SND_SWITCH_ACTIVATED, HSCREENW );
147 } else if(pf->board[x][y]->type==SWON){
148 sndPlay( SND_SWITCH_DEACTIVATED, HSCREENW );
149 } else if(newState && pf->board[x][y]->type==SWOFF)
150 {
151 sndPlay( SND_SWITCH_DEACTIVATED, HSCREENW );
152 } else if(pf->board[x][y]->type==SWOFF){
153 sndPlay( SND_SWITCH_ACTIVATED, HSCREENW );
154 }
155
156 }
157 }
158
switchAffectTarget(playField * pf,int x,int y,int newState)159 void switchAffectTarget( playField* pf, int x, int y, int newState )
160 {
161 brickType* s = pf->board[x][y];
162
163 switch( s->target->type )
164 {
165 // Walls are lifted off the board and placed in deactivated.
166 case STDWALL:
167
168
169 s->target->isActive = newState;
170
171 //We turn off the brick. (if the brick is there, it might not be as we could have lifted it off, placed a brick at destination, and moved off the switch and now try to lift it again)
172 if( !newState && (pf->board[ s->target->dx ][ s->target->dy ]==s->target) )
173 {
174 listAppendData( pf->deactivated, (void*)s->target );
175 pf->board[ s->target->dx ][ s->target->dy ]=NULL;
176 }
177 boardSetWalls( pf );
178 break;
179
180 //These types only have their active flag modified.
181 case GLUE:
182 case MOVERHORIZ:
183 case MOVERVERT:
184 case ONEWAYLEFT:
185 case ONEWAYRIGHT:
186 case EVILBRICK:
187 case COPYBRICK:
188 case REMBRICK:
189 case SWAPBRICK:
190 s->target->isActive = newState;
191 break;
192
193 //Teleports will watch for switches and need no modification.
194 case RESERVED:
195
196 break;
197
198 default:
199 printf( "Switch error: Type %i not handled.\n", s->target->type );
200 break;
201 }
202 //Let's have some particles
203 psysSpawnPreset(PSYS_PRESET_COLOR, (s->target->pxx+stealGfxPtr()->tiles[s->target->type-1]->clip.w/2), (s->target->pxy+stealGfxPtr()->tiles[s->target->type-1]->clip.h/2), 25,250 );
204
205 }
206
switchUpdateAll(playField * pf)207 void switchUpdateAll( playField* pf )
208 {
209 listItem* it = &pf->levelInfo->switchList->begin;
210
211 while( LISTFWD(pf->levelInfo->switchList, it) )
212 {
213 telePort_t* sw = (telePort_t*)it->data;
214 switchReact(pf, sw->sx, sw->sy );
215 }
216 }
217
switchPutBack(playField * pf)218 void switchPutBack(playField* pf)
219 {
220 //Now we put down activated bricks from list:
221 listItem* it = &pf->deactivated->begin;
222 while( LISTFWD(pf->deactivated,it) )
223 {
224 brickType* b = (brickType*)it->data;
225 if( b->isActive )
226 {
227 if(!pf->board[b->dx][b->dy])
228 {
229 pf->board[b->dx][b->dy]=b;
230 boardSetWalls(pf);
231 it=listRemoveItem(pf->deactivated,it, LIST_PREV);
232 }
233 }
234 }
235 }
236
237