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