1 /***************************************************************************
2 minimap.cpp - The ingame minimap
3 -------------------
4 begin : Thu Jan 29 2004
5 copyright : (C) 2004 by Daroth-U
6 email : daroth-u@ifrance.com
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "common/constants.h"
19 #include "minimap.h"
20 #include "render/renderlib.h"
21 #include "sdlhandler.h"
22 #include "dungeongenerator.h"
23 #include "scourge.h"
24 #include "math.h"
25 #include "gui/canvas.h"
26 #include "item.h"
27 #include "creature.h"
28 #include "shapepalette.h"
29 #include "rpg/rpglib.h"
30
31 using namespace std;
32
33 #define DEBUG_MINIMAP 0
34 #define MINI_MAP_OFFSET_X 30
35 #define MINI_MAP_OFFSET_Y 50
36 #define MINI_MAP_SIZE 60
37 #define MINI_MAP_BLOCK 4
38
MiniMap(Scourge * scourge)39 MiniMap :: MiniMap( Scourge *scourge ) {
40 this->scourge = scourge;
41 showMiniMap = true;
42 textureSizeH = textureSizeW = 512;
43 }
44
~MiniMap()45 MiniMap :: ~MiniMap() {
46 }
47
drawMap()48 void MiniMap::drawMap() {
49 if ( !showMiniMap ) return;
50
51 bool useStencil =
52 ( scourge->getPreferences()->getStencilbuf() &&
53 scourge->getPreferences()->getStencilBufInitialized() );
54
55 int sx = scourge->getSession()->getMap()->getX() + 75 - 30 - ( MINI_MAP_SIZE / 2 );
56 if ( sx < MAP_OFFSET ) sx = MAP_OFFSET;
57 int sy = scourge->getSession()->getMap()->getY() + 75 - 30 - ( MINI_MAP_SIZE / 2 );
58 if ( sy < MAP_OFFSET ) sy = MAP_OFFSET;
59 int ex = sx + MINI_MAP_SIZE;
60 if ( ex > textureSizeW ) ex = textureSizeW;
61 int ey = sy + MINI_MAP_SIZE;
62 if ( ey > textureSizeH ) ey = textureSizeW;
63
64 glDisable( GL_CULL_FACE );
65 glDisable( GL_DEPTH_TEST );
66 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
67
68 // Set rotation/translation for all following drawing operations.
69 glPushMatrix();
70 glLoadIdentity();
71 glTranslatef( MINI_MAP_OFFSET_X, MINI_MAP_OFFSET_Y, 0 );
72 glTranslatef( MINI_MAP_SIZE * MINI_MAP_BLOCK / 2, MINI_MAP_SIZE * MINI_MAP_BLOCK / 2, 0 );
73 glRotatef( scourge->getSession()->getMap()->getZRot(), 0, 0, 1 );
74 glTranslatef( -MINI_MAP_SIZE * MINI_MAP_BLOCK / 2, -MINI_MAP_SIZE * MINI_MAP_BLOCK / 2, 0 );
75
76 // Create the stencil from the minimap mask texture.
77 if ( useStencil ) {
78 glClear( GL_STENCIL_BUFFER_BIT );
79 glColorMask( 0, 0, 0, 0 );
80 glEnable( GL_STENCIL_TEST );
81 glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE );
82 glStencilFunc( GL_ALWAYS, 1, 0xffffffff );
83
84 glPushMatrix();
85 glDisable( GL_BLEND );
86 glEnable( GL_ALPHA_TEST );
87 //glAlphaFunc( GL_EQUAL, 0xff );
88 glAlphaFunc( GL_NOTEQUAL, 0 );
89 glEnable( GL_TEXTURE_2D );
90 scourge->getShapePalette()->getMinimapMaskTexture().glBind();
91 glColor4f( 1, 1, 1, 1 );
92 glBegin( GL_TRIANGLE_STRIP );
93 glTexCoord2f( 0, 0 );
94 glVertex2d( 0, 0 );
95 glTexCoord2f( 1, 0 );
96 glVertex2d( MINI_MAP_SIZE * MINI_MAP_BLOCK, 0 );
97 glTexCoord2f( 0, 1 );
98 glVertex2d( 0, MINI_MAP_SIZE * MINI_MAP_BLOCK );
99 glTexCoord2f( 1, 1 );
100 glVertex2d( MINI_MAP_SIZE * MINI_MAP_BLOCK, MINI_MAP_SIZE * MINI_MAP_BLOCK );
101 glEnd();
102 glDisable( GL_TEXTURE_2D );
103 glDisable( GL_ALPHA_TEST );
104 glPopMatrix();
105
106 glColorMask( 1, 1, 1, 1 );
107 glStencilFunc( GL_EQUAL, 1, 0xffffffff );
108 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
109 glDepthMask( GL_FALSE );
110
111 // Draw the transparent background.
112 glPushMatrix();
113 glEnable( GL_BLEND );
114 glEnable( GL_TEXTURE_2D );
115 scourge->getShapePalette()->getMinimapMaskTexture().glBind();
116 glColor4f( 0, 0, 0, 0.5f );
117 glBegin( GL_TRIANGLE_STRIP );
118 glTexCoord2f( 0, 0 );
119 glVertex2d( 0, 0 );
120 glTexCoord2f( 1, 0 );
121 glVertex2d( MINI_MAP_SIZE * MINI_MAP_BLOCK, 0 );
122 glTexCoord2f( 0, 1 );
123 glVertex2d( 0, MINI_MAP_SIZE * MINI_MAP_BLOCK );
124 glTexCoord2f( 1, 1 );
125 glVertex2d( MINI_MAP_SIZE * MINI_MAP_BLOCK, MINI_MAP_SIZE * MINI_MAP_BLOCK );
126 glEnd();
127 glDisable( GL_TEXTURE_2D );
128 glPopMatrix();
129 } else {
130 // Draw north marker and outline for the "simple" non-stencil version.
131 glEnable( GL_BLEND );
132
133 glColor4f( 0.5f, 0.5f, 0.5f, 0.5f );
134 glBegin( GL_TRIANGLES );
135 glVertex2f( 0, 0 );
136 glVertex2f( 30, 0 );
137 glVertex2f( 0, 30 );
138 glEnd();
139 glPushMatrix();
140 glRotatef( -45, 0, 0, 1 );
141 glTranslatef( -7, 20, 0 );
142 glScalef( 1.5f, 1.5f, 1.5f );
143 glColor4f( 1, 1, 1, 0.5f );
144 scourge->getSDLHandler()->texPrint( 0, 0, "N" );
145 glScalef( 1, 1, 1 );
146 glPopMatrix();
147
148 // outline
149 glColor4f( 0.5f, 0.5f, 0.5f, 0.5f );
150 glBegin( GL_LINE_LOOP );
151 glVertex2f( 0, 0 );
152 glVertex2f( 0, MINI_MAP_SIZE * MINI_MAP_BLOCK );
153 glVertex2f( MINI_MAP_SIZE * MINI_MAP_BLOCK, MINI_MAP_SIZE * MINI_MAP_BLOCK );
154 glVertex2f( MINI_MAP_SIZE * MINI_MAP_BLOCK, 0 );
155 glEnd();
156 }
157
158 // Draw the surrounding objects into the map. Naive method: draw each block.
159 for ( int x = sx; x < ex; x++ ) {
160 if ( x < 0 || x >= MAP_WIDTH ) continue;
161 for ( int y = sy; y < ey; y++ ) {
162 if ( y < 0 || y >= MAP_DEPTH ) continue;
163 Location *pos = scourge->getSession()->getMap()->getLocation( x, y, 0 );
164
165 if ( pos ) {
166
167 if ( pos->shape ) {
168
169 if ( !pos->creature ) {
170
171 if ( pos->item ) {
172 glColor4f( 0, 0, 1, 0.5f );
173 } else {
174 if ( !pos->shape->isInteractive() ) {
175 glColor4f( 1, 1, 1, 0.5f );
176 } else {
177 glColor4f( 1, 0.7f, 0, 0.5f );
178 }
179 }
180
181 float xp = ( x - sx ) * MINI_MAP_BLOCK;
182 float yp = ( y - sy ) * MINI_MAP_BLOCK;
183
184 glBegin( GL_TRIANGLE_STRIP );
185 glVertex2f( xp, yp );
186 glVertex2f( xp + MINI_MAP_BLOCK, yp );
187 glVertex2f( xp, yp + MINI_MAP_BLOCK );
188 glVertex2f( xp + MINI_MAP_BLOCK, yp + MINI_MAP_BLOCK );
189 glEnd();
190
191 } else {
192
193 if ( pos->creature->isMonster() ) {
194 glColor4f( 1, 0, 0, 0.5f );
195 } else if ( pos->creature->isNpc() ) {
196 glColor4f( 0.8f, 0.8f, 0, 0.5f );
197 } else {
198 if ( pos->creature == scourge->getSession()->getParty()->getPlayer() ) {
199 glColor4f( 0, 1, 0, 0.5f );
200 } else {
201 glColor4f( 0, 0.8f, 0.8f, 0.5f );
202 for ( int c = 0; c < scourge->getParty()->getPartySize(); c++ ) {
203 if ( pos->creature == scourge->getSession()->getParty()->getParty( c ) ) {
204 glColor4f( 0, 0.8f, 0, 0.5f );
205 break;
206 }
207 }
208 }
209 }
210
211 float width = pos->creature->getShape()->getWidth() / 2.0f * MINI_MAP_BLOCK;
212 float cx = ( pos->creature->getX() - sx ) * MINI_MAP_BLOCK + width;
213 float cy = ( pos->creature->getY() - sy ) * MINI_MAP_BLOCK - width;
214
215 glPushMatrix();
216 glTranslatef( cx, cy, 0 );
217 glRotatef( ( ( AnimatedShape* )pos->creature->getShape() )->getAngle(), 0, 0, 1 );
218 glBegin( GL_TRIANGLES );
219 glVertex2f( width, width );
220 glVertex2f( -width, width );
221 glVertex2f( 0, -width );
222 glEnd();
223 glPopMatrix();
224
225 }
226
227 }
228
229 }
230
231 }
232 }
233
234 // Draw the minimap frame.
235 if ( useStencil ) {
236 glDepthMask( GL_TRUE );
237 glDisable( GL_STENCIL_TEST );
238
239 glPushMatrix();
240 glEnable( GL_ALPHA_TEST );
241 glAlphaFunc( GL_ALWAYS, 0 );
242 glEnable( GL_TEXTURE_2D );
243 scourge->getShapePalette()->getMinimapTexture().glBind();
244 glColor4f( 1, 1, 1, 1 );
245 glBegin( GL_TRIANGLE_STRIP );
246 glTexCoord2f( 0, 0 );
247 glVertex2d( 0, 0 );
248 glTexCoord2f( 1, 0 );
249 glVertex2d( MINI_MAP_SIZE * MINI_MAP_BLOCK, 0 );
250 glTexCoord2f( 0, 1 );
251 glVertex2d( 0, MINI_MAP_SIZE * MINI_MAP_BLOCK );
252 glTexCoord2f( 1, 1 );
253 glVertex2d( MINI_MAP_SIZE * MINI_MAP_BLOCK, MINI_MAP_SIZE * MINI_MAP_BLOCK );
254 glEnd();
255 glDisable( GL_TEXTURE_2D );
256 glDisable( GL_ALPHA_TEST );
257 glPopMatrix();
258
259 // draw pointers for gates and teleporters
260 if ( scourge->getParty() && scourge->getParty()->getPartySize() ) {
261 drawPointers( scourge->getSession()->getMap()->getGates(), Color( 1, 0, 0, 1 ) );
262 drawPointers( scourge->getSession()->getMap()->getTeleporters(), Color( 0, 0, 1, 1 ) );
263 }
264 }
265
266 glPopMatrix();
267 glDisable( GL_BLEND );
268 glEnable( GL_CULL_FACE );
269 glEnable( GL_DEPTH_TEST );
270 glEnable( GL_TEXTURE_2D );
271 }
272
drawPointers(std::set<Location * > * p,Color color)273 void MiniMap::drawPointers( std::set<Location*> *p, Color color ) {
274 // player's pos
275 float px = scourge->getParty()->getPlayer()->getX();
276 float py = scourge->getParty()->getPlayer()->getY();
277
278 // center coord. of minimap
279 float r = MINI_MAP_SIZE * MINI_MAP_BLOCK / 2;
280
281 for ( set<Location*>::iterator e = p->begin(); e != p->end(); ++e ) {
282 Location *pos = *e;
283 float angle = Util::getAngle( px, py, 0, 0, ( float )pos->x, ( float )pos->y, 0, 0 );
284 float nx = r + ( r - 10 ) * Constants::cosFromAngle( angle ) - 5;
285 float ny = r + ( r - 10 ) * Constants::sinFromAngle( angle );
286 glColor4f( color.r, color.g, color.b, color.a );
287 glBegin( GL_TRIANGLE_STRIP );
288 glVertex2d( nx, ny );
289 glVertex2d( nx + 4, ny );
290 glVertex2d( nx, ny + 4 );
291 glVertex2d( nx + 4, ny + 4 );
292 glEnd();
293 glColor4f( 0, 0, 0, 1 );
294 glBegin( GL_LINE_LOOP );
295 glVertex2d( nx - 1, ny + 6 );
296 glVertex2d( nx + 6, ny + 6 );
297 glVertex2d( nx + 6, ny - 1 );
298 glVertex2d( nx - 1, ny - 1 );
299 glEnd();
300 }
301 glColor4f( 1, 1, 1, 1 );
302 }
303